Scale texture sizes to fit within available memory
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cShaderImageLoadStoreTests.cpp
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 "vkPlatform.hpp"
32 #include <assert.h>
33 #include <climits>
34 #include <cmath>
35 #include <cstdarg>
36 #include <deque>
37 #include <iomanip>
38 #include <map>
39 #include <sstream>
40 #include <tcuFloat.hpp>
41
42 namespace gl4cts
43 {
44 using namespace glw;
45
46 namespace
47 {
48 typedef tcu::Vec2  vec2;
49 typedef tcu::Vec4  vec4;
50 typedef tcu::IVec4 ivec4;
51 typedef tcu::UVec4 uvec4;
52 typedef tcu::Mat4  mat4;
53
54 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
55 {
56         virtual std::string Title()
57         {
58                 return "";
59         }
60
61         virtual std::string Purpose()
62         {
63                 return "";
64         }
65
66         virtual std::string Method()
67         {
68                 return "";
69         }
70
71         virtual std::string PassCriteria()
72         {
73                 return "";
74         }
75
76 public:
77         bool SupportedInVS(int requiredVS)
78         {
79                 GLint imagesVS;
80                 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
81                 if (imagesVS >= requiredVS)
82                         return true;
83                 else
84                 {
85                         std::ostringstream reason;
86                         reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
87                                    << std::endl;
88                         OutputNotSupported(reason.str());
89                         return false;
90                 }
91         }
92
93         bool SupportedInTCS(int requiredTCS)
94         {
95                 GLint imagesTCS;
96                 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
97                 if (imagesTCS >= requiredTCS)
98                         return true;
99                 else
100                 {
101                         std::ostringstream reason;
102                         reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
103                                    << std::endl;
104                         OutputNotSupported(reason.str());
105                         return false;
106                 }
107         }
108
109         bool SupportedInTES(int requiredTES)
110         {
111                 GLint imagesTES;
112                 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
113                 if (imagesTES >= requiredTES)
114                         return true;
115                 else
116                 {
117                         std::ostringstream reason;
118                         reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
119                                    << std::endl;
120                         OutputNotSupported(reason.str());
121                         return false;
122                 }
123         }
124
125         bool SupportedInGS(int requiredGS)
126         {
127                 GLint imagesGS;
128                 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
129                 if (imagesGS >= requiredGS)
130                         return true;
131                 else
132                 {
133                         std::ostringstream reason;
134                         reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
135                                    << std::endl;
136                         OutputNotSupported(reason.str());
137                         return false;
138                 }
139         }
140
141         bool SupportedInGeomStages(int required)
142         {
143                 return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
144                            SupportedInGS(required);
145         }
146
147         bool SupportedInStage(int stage, int required)
148         {
149                 switch (stage)
150                 {
151                 case 0:
152                         return SupportedInVS(required);
153                 case 1:
154                         return SupportedInTCS(required);
155                 case 2:
156                         return SupportedInTES(required);
157                 case 3:
158                         return SupportedInGS(required);
159                 default:
160                         return true;
161                 }
162         }
163
164         bool SupportedSamples(int required)
165         {
166                 int i;
167                 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
168                 if (i >= required)
169                         return true;
170                 else
171                 {
172                         std::ostringstream reason;
173                         reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
174                         OutputNotSupported(reason.str());
175                         return false;
176                 }
177         }
178
179         int getWindowWidth()
180         {
181                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
182                 return renderTarget.getWidth();
183         }
184
185         int getWindowHeight()
186         {
187                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
188                 return renderTarget.getHeight();
189         }
190
191         void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
192         {
193                 vk::PlatformMemoryLimits memoryLimits;
194                 m_context.getTestContext().getPlatform().getVulkanPlatform().getMemoryLimits(memoryLimits);
195                 GLsizeiptr sysSpace               = memoryLimits.totalSystemMemory;
196                 GLsizeiptr devSpace               = memoryLimits.totalDeviceLocalMemory;
197                 int                devInSysLayers = 0;
198
199                 if (devSpace == 0)
200                 {
201                         devInSysLayers = devLayers;
202                         devLayers         = 0;
203                 }
204
205                 // Check if available memory is enough
206                 GLsizeiptr pixelsPerLayer = width * height;
207                 GLsizeiptr sysRequired  = pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
208                 GLsizeiptr devRequired  = pixelsPerLayer * devBPP * devLayers;
209                 if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
210                 {
211                         return;
212                 }
213
214                 // Scales the width and height such that the overall texture fits into
215                 // the available space for both system and device.
216                 GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
217                 if (devSpace != 0)
218                 {
219                         GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
220                         scale                     = de::min(devScale, scale);
221                 }
222                 int newWidth  = int(width * scale);
223                 int newHeight = int(height * scale);
224
225                 m_context.getTestContext().getLog()
226                         << tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
227                         << " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
228
229                 width  = newWidth;
230                 height = newHeight;
231         }
232
233         inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
234         {
235                 if (fabs(c0[0] - c1[0]) > epsilon[0])
236                         return false;
237                 if (fabs(c0[1] - c1[1]) > epsilon[1])
238                         return false;
239                 if (fabs(c0[2] - c1[2]) > epsilon[2])
240                         return false;
241                 if (fabs(c0[3] - c1[3]) > epsilon[3])
242                         return false;
243                 return true;
244         }
245
246         bool IsEqual(vec4 a, vec4 b)
247         {
248                 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
249         }
250
251         bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
252         {
253                 if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
254                 {
255                         return ColorEqual(v0, v1, vec4(0.0001f));
256                 }
257                 else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
258                 {
259                         return ColorEqual(v0, v1, vec4(0.01f));
260                 }
261                 return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
262         }
263
264         bool Equal(const ivec4& a, const ivec4& b, GLenum)
265         {
266                 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
267         }
268
269         bool Equal(const uvec4& a, const uvec4& b, GLenum)
270         {
271                 return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
272         }
273
274         template <class T>
275         std::string ToString(T v)
276         {
277                 std::ostringstream s;
278                 s << "[";
279                 for (int i = 0; i < 4; ++i)
280                         s << v[i] << (i == 3 ? "" : ",");
281                 s << "]";
282                 return s.str();
283         }
284
285         bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
286         {
287                 bool                                     status           = true;
288                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
289                 const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
290                 vec4                                     g_color_eps  = vec4(
291                         1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
292                         1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
293
294                 std::vector<vec4> fb(w * h);
295                 glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
296
297                 for (int yy = 0; yy < h; ++yy)
298                 {
299                         for (int xx = 0; xx < w; ++xx)
300                         {
301                                 const int idx = yy * w + xx;
302                                 if (!ColorEqual(fb[idx], expected, g_color_eps))
303                                 {
304                                         m_context.getTestContext().getLog()
305                                                 << tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
306                                                 << tcu::TestLog::EndMessage;
307                                         status = false;
308                                         return status;
309                                 }
310                         }
311                 }
312                 return status;
313         }
314
315         bool CompileShader(GLuint shader)
316         {
317                 glCompileShader(shader);
318
319                 GLint status;
320                 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
321                 if (status == GL_FALSE)
322                 {
323                         GLsizei length;
324                         GLchar  log[1024];
325                         glGetShaderInfoLog(shader, sizeof(log), &length, log);
326                         if (length > 1)
327                         {
328                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
329                                                                                                         << log << tcu::TestLog::EndMessage;
330                         }
331                         return false;
332                 }
333                 return true;
334         }
335
336         bool LinkProgram(GLuint program)
337         {
338                 glLinkProgram(program);
339
340                 GLint status;
341                 glGetProgramiv(program, GL_LINK_STATUS, &status);
342                 if (status == GL_FALSE)
343                 {
344                         GLsizei length;
345                         GLchar  log[1024];
346                         glGetProgramInfoLog(program, sizeof(log), &length, log);
347                         if (length > 1)
348                         {
349                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
350                                                                                                         << log << tcu::TestLog::EndMessage;
351                         }
352                         return false;
353                 }
354                 return true;
355         }
356
357         GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
358                                                 const char* src_fs, bool* result = NULL)
359         {
360                 const GLuint p = glCreateProgram();
361
362                 if (src_vs)
363                 {
364                         GLuint sh = glCreateShader(GL_VERTEX_SHADER);
365                         glAttachShader(p, sh);
366                         glDeleteShader(sh);
367                         glShaderSource(sh, 1, &src_vs, NULL);
368                         if (!CompileShader(sh))
369                         {
370                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
371                                 if (result)
372                                         *result = false;
373                                 return p;
374                         }
375                 }
376                 if (src_tcs)
377                 {
378                         GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
379                         glAttachShader(p, sh);
380                         glDeleteShader(sh);
381                         glShaderSource(sh, 1, &src_tcs, NULL);
382                         if (!CompileShader(sh))
383                         {
384                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
385                                 if (result)
386                                         *result = false;
387                                 return p;
388                         }
389                 }
390                 if (src_tes)
391                 {
392                         GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
393                         glAttachShader(p, sh);
394                         glDeleteShader(sh);
395                         glShaderSource(sh, 1, &src_tes, NULL);
396                         if (!CompileShader(sh))
397                         {
398                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
399                                 if (result)
400                                         *result = false;
401                                 return p;
402                         }
403                 }
404                 if (src_gs)
405                 {
406                         GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
407                         glAttachShader(p, sh);
408                         glDeleteShader(sh);
409                         glShaderSource(sh, 1, &src_gs, NULL);
410                         if (!CompileShader(sh))
411                         {
412                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
413                                 if (result)
414                                         *result = false;
415                                 return p;
416                         }
417                 }
418                 if (src_fs)
419                 {
420                         GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
421                         glAttachShader(p, sh);
422                         glDeleteShader(sh);
423                         glShaderSource(sh, 1, &src_fs, NULL);
424                         if (!CompileShader(sh))
425                         {
426                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
427                                 if (result)
428                                         *result = false;
429                                 return p;
430                         }
431                 }
432                 if (!LinkProgram(p))
433                 {
434                         if (src_vs)
435                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
436                         if (src_tcs)
437                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
438                         if (src_tes)
439                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
440                         if (src_gs)
441                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
442                         if (src_fs)
443                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
444                         if (result)
445                                 *result = false;
446                         return p;
447                 }
448
449                 return p;
450         }
451
452         GLuint BuildShaderProgram(GLenum type, const char* src)
453         {
454                 const GLuint p = glCreateShaderProgramv(type, 1, &src);
455
456                 GLint status;
457                 glGetProgramiv(p, GL_LINK_STATUS, &status);
458                 if (status == GL_FALSE)
459                 {
460                         GLchar log[1024];
461                         glGetProgramInfoLog(p, sizeof(log), NULL, log);
462                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
463                                                                                                 << log << "\n"
464                                                                                                 << src << tcu::TestLog::EndMessage;
465                 }
466
467                 return p;
468         }
469
470         void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
471         {
472                 assert(vao && vbo);
473
474                 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
475                 const float v[] = {
476                         -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,  1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
477                         0.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f,
478                         1.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f,  0.0f,
479                 };
480                 glGenBuffers(1, vbo);
481                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
482                 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
483                 glBindBuffer(GL_ARRAY_BUFFER, 0);
484
485                 if (ebo)
486                 {
487                         std::vector<GLushort> index_data(4);
488                         for (int i = 0; i < 4; ++i)
489                         {
490                                 index_data[i] = static_cast<GLushort>(i);
491                         }
492                         glGenBuffers(1, ebo);
493                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
494                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
495                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
496                 }
497
498                 glGenVertexArrays(1, vao);
499                 glBindVertexArray(*vao);
500                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
501                 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
502                 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
503                 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
504                 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
505                 glBindBuffer(GL_ARRAY_BUFFER, 0);
506                 glEnableVertexAttribArray(0);
507                 glEnableVertexAttribArray(1);
508                 glEnableVertexAttribArray(2);
509                 glEnableVertexAttribArray(3);
510                 if (ebo)
511                 {
512                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
513                 }
514                 glBindVertexArray(0);
515         }
516
517         std::string FormatEnumToString(GLenum e)
518         {
519                 switch (e)
520                 {
521                 case GL_RGBA32F:
522                         return "rgba32f";
523                 case GL_RGBA16F:
524                         return "rgba16f";
525                 case GL_RG32F:
526                         return "rg32f";
527                 case GL_RG16F:
528                         return "rg16f";
529                 case GL_R11F_G11F_B10F:
530                         return "r11f_g11f_b10f";
531                 case GL_R32F:
532                         return "r32f";
533                 case GL_R16F:
534                         return "r16f";
535
536                 case GL_RGBA32UI:
537                         return "rgba32ui";
538                 case GL_RGBA16UI:
539                         return "rgba16ui";
540                 case GL_RGB10_A2UI:
541                         return "rgb10_a2ui";
542                 case GL_RGBA8UI:
543                         return "rgba8ui";
544                 case GL_RG32UI:
545                         return "rg32ui";
546                 case GL_RG16UI:
547                         return "rg16ui";
548                 case GL_RG8UI:
549                         return "rg8ui";
550                 case GL_R32UI:
551                         return "r32ui";
552                 case GL_R16UI:
553                         return "r16ui";
554                 case GL_R8UI:
555                         return "r8ui";
556
557                 case GL_RGBA32I:
558                         return "rgba32i";
559                 case GL_RGBA16I:
560                         return "rgba16i";
561                 case GL_RGBA8I:
562                         return "rgba8i";
563                 case GL_RG32I:
564                         return "rg32i";
565                 case GL_RG16I:
566                         return "rg16i";
567                 case GL_RG8I:
568                         return "rg8i";
569                 case GL_R32I:
570                         return "r32i";
571                 case GL_R16I:
572                         return "r16i";
573                 case GL_R8I:
574                         return "r8i";
575
576                 case GL_RGBA16:
577                         return "rgba16";
578                 case GL_RGB10_A2:
579                         return "rgb10_a2";
580                 case GL_RGBA8:
581                         return "rgba8";
582                 case GL_RG16:
583                         return "rg16";
584                 case GL_RG8:
585                         return "rg8";
586                 case GL_R16:
587                         return "r16";
588                 case GL_R8:
589                         return "r8";
590
591                 case GL_RGBA16_SNORM:
592                         return "rgba16_snorm";
593                 case GL_RGBA8_SNORM:
594                         return "rgba8_snorm";
595                 case GL_RG16_SNORM:
596                         return "rg16_snorm";
597                 case GL_RG8_SNORM:
598                         return "rg8_snorm";
599                 case GL_R16_SNORM:
600                         return "r16_snorm";
601                 case GL_R8_SNORM:
602                         return "r8_snorm";
603                 }
604
605                 assert(0);
606                 return "";
607         }
608
609         const char* StageName(int stage)
610         {
611                 switch (stage)
612                 {
613                 case 0:
614                         return "Vertex Shader";
615                 case 1:
616                         return "Tessellation Control Shader";
617                 case 2:
618                         return "Tessellation Evaluation Shader";
619                 case 3:
620                         return "Geometry Shader";
621                 case 4:
622                         return "Compute Shader";
623                 }
624                 assert(0);
625                 return NULL;
626         }
627
628         template <typename T>
629         GLenum Format();
630
631         template <typename T>
632         GLenum Type();
633
634         template <typename T>
635         std::string TypePrefix();
636
637         template <typename T>
638         GLenum ImageType(GLenum target);
639
640         void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
641         {
642                 glClearBufferfv(buffer, drawbuffer, &color[0]);
643         }
644
645         void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
646         {
647                 glClearBufferiv(buffer, drawbuffer, &color[0]);
648         }
649
650         void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
651         {
652                 glClearBufferuiv(buffer, drawbuffer, &color[0]);
653         }
654
655         bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
656                                           GLint size, GLenum type)
657         {
658                 std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
659                 assert(iter != name_index_map.end());
660
661                 GLchar  name_gl[32];
662                 GLsizei length_gl;
663                 GLint   size_gl;
664                 GLenum  type_gl;
665
666                 glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
667
668                 if (std::string(name_gl) != name)
669                 {
670                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
671                                                                                                 << " should be " << name << tcu::TestLog::EndMessage;
672                         return false;
673                 }
674                 if (length_gl != static_cast<GLsizei>(name.length()))
675                 {
676                         m_context.getTestContext().getLog()
677                                 << tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
678                                 << ")" << tcu::TestLog::EndMessage;
679                         return false;
680                 }
681                 if (size_gl != size)
682                 {
683                         m_context.getTestContext().getLog()
684                                 << tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
685                                 << ")" << tcu::TestLog::EndMessage;
686                         return false;
687                 }
688                 if (type_gl != type)
689                 {
690                         m_context.getTestContext().getLog()
691                                 << tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
692                                 << ")" << tcu::TestLog::EndMessage;
693                         return false;
694                 }
695
696                 return true;
697         }
698
699         bool CheckMax(GLenum pname, GLint min_value)
700         {
701                 GLboolean b;
702                 GLint    i;
703                 GLfloat   f;
704                 GLdouble  d;
705                 GLint64   i64;
706
707                 glGetIntegerv(pname, &i);
708                 if (i < min_value)
709                         return false;
710
711                 glGetBooleanv(pname, &b);
712                 if (b != (i ? GL_TRUE : GL_FALSE))
713                         return false;
714
715                 glGetFloatv(pname, &f);
716                 if (static_cast<GLint>(f) < min_value)
717                         return false;
718
719                 glGetDoublev(pname, &d);
720                 if (static_cast<GLint>(d) < min_value)
721                         return false;
722
723                 glGetInteger64v(pname, &i64);
724                 if (static_cast<GLint>(i64) < min_value)
725                         return false;
726
727                 return true;
728         }
729
730         bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
731                                           GLenum format)
732         {
733                 GLint    i;
734                 GLboolean b;
735
736                 glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
737                 if (static_cast<GLuint>(i) != texture)
738                 {
739                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
740                                                                                                 << " should be " << texture << tcu::TestLog::EndMessage;
741                         return false;
742                 }
743                 glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
744                 if (b != (i ? GL_TRUE : GL_FALSE))
745                 {
746                         m_context.getTestContext().getLog()
747                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
748                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
749                         return false;
750                 }
751
752                 glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
753                 if (i != level)
754                 {
755                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
756                                                                                                 << " should be " << level << tcu::TestLog::EndMessage;
757                         return false;
758                 }
759                 glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
760                 if (b != (i ? GL_TRUE : GL_FALSE))
761                 {
762                         m_context.getTestContext().getLog()
763                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
764                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
765                         return false;
766                 }
767
768                 glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
769                 if (i != layered)
770                 {
771                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
772                                                                                                 << " should be " << layered << tcu::TestLog::EndMessage;
773                         return false;
774                 }
775                 glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
776                 if (b != (i ? GL_TRUE : GL_FALSE))
777                 {
778                         m_context.getTestContext().getLog()
779                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
780                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
781                         return false;
782                 }
783
784                 glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
785                 if (i != layer)
786                 {
787                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
788                                                                                                 << " should be " << layer << tcu::TestLog::EndMessage;
789                         return false;
790                 }
791                 glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
792                 if (b != (i ? GL_TRUE : GL_FALSE))
793                 {
794                         m_context.getTestContext().getLog()
795                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
796                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
797                         return false;
798                 }
799
800                 glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
801                 if (static_cast<GLenum>(i) != access)
802                 {
803                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
804                                                                                                 << " should be " << access << tcu::TestLog::EndMessage;
805                         return false;
806                 }
807                 glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
808                 if (b != (i ? GL_TRUE : GL_FALSE))
809                 {
810                         m_context.getTestContext().getLog()
811                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
812                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
813                         return false;
814                 }
815
816                 glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
817                 if (static_cast<GLenum>(i) != format)
818                 {
819                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
820                                                                                                 << " should be " << format << tcu::TestLog::EndMessage;
821                         return false;
822                 }
823                 glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
824                 if (b != (i ? GL_TRUE : GL_FALSE))
825                 {
826                         m_context.getTestContext().getLog()
827                                 << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
828                                 << (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
829                         return false;
830                 }
831
832                 return true;
833         }
834         const char* EnumToString(GLenum e)
835         {
836                 switch (e)
837                 {
838                 case GL_TEXTURE_1D:
839                         return "GL_TEXTURE_1D";
840                 case GL_TEXTURE_2D:
841                         return "GL_TEXTURE_2D";
842                 case GL_TEXTURE_3D:
843                         return "GL_TEXTURE_3D";
844                 case GL_TEXTURE_RECTANGLE:
845                         return "GL_TEXTURE_RECTANGLE";
846                 case GL_TEXTURE_CUBE_MAP:
847                         return "GL_TEXTURE_CUBE_MAP";
848                 case GL_TEXTURE_1D_ARRAY:
849                         return "GL_TEXTURE_1D_ARRAY";
850                 case GL_TEXTURE_2D_ARRAY:
851                         return "GL_TEXTURE_2D_ARRAY";
852                 case GL_TEXTURE_CUBE_MAP_ARRAY:
853                         return "GL_TEXTURE_CUBE_MAP_ARRAY";
854
855                 default:
856                         assert(0);
857                         break;
858                 }
859                 return NULL;
860         }
861 };
862
863 template <>
864 GLenum ShaderImageLoadStoreBase::Format<vec4>()
865 {
866         return GL_RGBA;
867 }
868
869 template <>
870 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
871 {
872         return GL_RGBA_INTEGER;
873 }
874
875 template <>
876 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
877 {
878         return GL_RGBA_INTEGER;
879 }
880
881 template <>
882 GLenum ShaderImageLoadStoreBase::Format<GLint>()
883 {
884         return GL_RED_INTEGER;
885 }
886
887 template <>
888 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
889 {
890         return GL_RED_INTEGER;
891 }
892
893 template <>
894 GLenum ShaderImageLoadStoreBase::Type<vec4>()
895 {
896         return GL_FLOAT;
897 }
898
899 template <>
900 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
901 {
902         return GL_INT;
903 }
904
905 template <>
906 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
907 {
908         return GL_UNSIGNED_INT;
909 }
910
911 template <>
912 GLenum ShaderImageLoadStoreBase::Type<GLint>()
913 {
914         return GL_INT;
915 }
916
917 template <>
918 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
919 {
920         return GL_UNSIGNED_INT;
921 }
922
923 template <>
924 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
925 {
926         return "";
927 }
928
929 template <>
930 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
931 {
932         return "i";
933 }
934
935 template <>
936 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
937 {
938         return "u";
939 }
940
941 template <>
942 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
943 {
944         return "i";
945 }
946
947 template <>
948 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
949 {
950         return "u";
951 }
952
953 template <>
954 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
955 {
956         switch (target)
957         {
958         case GL_TEXTURE_1D:
959                 return GL_IMAGE_1D;
960         case GL_TEXTURE_2D:
961                 return GL_IMAGE_2D;
962         case GL_TEXTURE_3D:
963                 return GL_IMAGE_3D;
964         case GL_TEXTURE_RECTANGLE:
965                 return GL_IMAGE_2D_RECT;
966         case GL_TEXTURE_CUBE_MAP:
967                 return GL_IMAGE_CUBE;
968         case GL_TEXTURE_BUFFER:
969                 return GL_IMAGE_BUFFER;
970         case GL_TEXTURE_1D_ARRAY:
971                 return GL_IMAGE_1D_ARRAY;
972         case GL_TEXTURE_2D_ARRAY:
973                 return GL_IMAGE_2D_ARRAY;
974         case GL_TEXTURE_CUBE_MAP_ARRAY:
975                 return GL_IMAGE_CUBE_MAP_ARRAY;
976         case GL_TEXTURE_2D_MULTISAMPLE:
977                 return GL_IMAGE_2D_MULTISAMPLE;
978         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
979                 return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
980         }
981         assert(0);
982         return 0;
983 }
984
985 template <>
986 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
987 {
988         switch (target)
989         {
990         case GL_TEXTURE_1D:
991                 return GL_INT_IMAGE_1D;
992         case GL_TEXTURE_2D:
993                 return GL_INT_IMAGE_2D;
994         case GL_TEXTURE_3D:
995                 return GL_INT_IMAGE_3D;
996         case GL_TEXTURE_RECTANGLE:
997                 return GL_INT_IMAGE_2D_RECT;
998         case GL_TEXTURE_CUBE_MAP:
999                 return GL_INT_IMAGE_CUBE;
1000         case GL_TEXTURE_BUFFER:
1001                 return GL_INT_IMAGE_BUFFER;
1002         case GL_TEXTURE_1D_ARRAY:
1003                 return GL_INT_IMAGE_1D_ARRAY;
1004         case GL_TEXTURE_2D_ARRAY:
1005                 return GL_INT_IMAGE_2D_ARRAY;
1006         case GL_TEXTURE_CUBE_MAP_ARRAY:
1007                 return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1008         case GL_TEXTURE_2D_MULTISAMPLE:
1009                 return GL_INT_IMAGE_2D_MULTISAMPLE;
1010         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1011                 return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1012         }
1013         assert(0);
1014         return 0;
1015 }
1016
1017 template <>
1018 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1019 {
1020         switch (target)
1021         {
1022         case GL_TEXTURE_1D:
1023                 return GL_UNSIGNED_INT_IMAGE_1D;
1024         case GL_TEXTURE_2D:
1025                 return GL_UNSIGNED_INT_IMAGE_2D;
1026         case GL_TEXTURE_3D:
1027                 return GL_UNSIGNED_INT_IMAGE_3D;
1028         case GL_TEXTURE_RECTANGLE:
1029                 return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1030         case GL_TEXTURE_CUBE_MAP:
1031                 return GL_UNSIGNED_INT_IMAGE_CUBE;
1032         case GL_TEXTURE_BUFFER:
1033                 return GL_UNSIGNED_INT_IMAGE_BUFFER;
1034         case GL_TEXTURE_1D_ARRAY:
1035                 return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1036         case GL_TEXTURE_2D_ARRAY:
1037                 return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1038         case GL_TEXTURE_CUBE_MAP_ARRAY:
1039                 return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1040         case GL_TEXTURE_2D_MULTISAMPLE:
1041                 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1042         case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1043                 return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1044         }
1045         assert(0);
1046         return 0;
1047 }
1048
1049 //-----------------------------------------------------------------------------
1050 // 1.1.1 BasicAPIGet
1051 //-----------------------------------------------------------------------------
1052 class BasicAPIGet : public ShaderImageLoadStoreBase
1053 {
1054         virtual long Run()
1055         {
1056                 if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1057                 {
1058                         m_context.getTestContext().getLog()
1059                                 << tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1060                         return ERROR;
1061                 }
1062                 if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1063                 {
1064                         m_context.getTestContext().getLog()
1065                                 << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1066                                 << tcu::TestLog::EndMessage;
1067                         return ERROR;
1068                 }
1069                 if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1070                 {
1071                         m_context.getTestContext().getLog()
1072                                 << tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1073                         return ERROR;
1074                 }
1075                 if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1076                 {
1077                         m_context.getTestContext().getLog()
1078                                 << tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1079                                 << tcu::TestLog::EndMessage;
1080                         return ERROR;
1081                 }
1082                 if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1083                 {
1084                         m_context.getTestContext().getLog()
1085                                 << tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1086                                 << tcu::TestLog::EndMessage;
1087                         return ERROR;
1088                 }
1089                 if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1090                 {
1091                         m_context.getTestContext().getLog()
1092                                 << tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1093                                 << tcu::TestLog::EndMessage;
1094                         return ERROR;
1095                 }
1096                 if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1097                 {
1098                         m_context.getTestContext().getLog()
1099                                 << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1100                                 << tcu::TestLog::EndMessage;
1101                         return ERROR;
1102                 }
1103                 if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1104                 {
1105                         m_context.getTestContext().getLog()
1106                                 << tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1107                                 << tcu::TestLog::EndMessage;
1108                         return ERROR;
1109                 }
1110                 if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1111                 {
1112                         m_context.getTestContext().getLog()
1113                                 << tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1114                                 << tcu::TestLog::EndMessage;
1115                         return ERROR;
1116                 }
1117                 return NO_ERROR;
1118         }
1119 };
1120 //-----------------------------------------------------------------------------
1121 // 1.1.2 BasicAPIBind
1122 //-----------------------------------------------------------------------------
1123 class BasicAPIBind : public ShaderImageLoadStoreBase
1124 {
1125         GLuint m_texture;
1126
1127         virtual long Setup()
1128         {
1129                 m_texture = 0;
1130                 return NO_ERROR;
1131         }
1132
1133         virtual long Run()
1134         {
1135                 for (GLuint index = 0; index < 8; ++index)
1136                 {
1137                         if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1138                         {
1139                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1140                                                                                                         << " has invalid default state." << tcu::TestLog::EndMessage;
1141                                 return ERROR;
1142                         }
1143                 }
1144
1145                 glGenTextures(1, &m_texture);
1146                 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1147                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1148                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1149                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1150                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1151                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1152                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1153
1154                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1155                 if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1156                         return ERROR;
1157
1158                 glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1159                 if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1160                         return ERROR;
1161
1162                 glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1163                 if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1164                         return ERROR;
1165
1166                 glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1167                 if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1168                         return ERROR;
1169
1170                 glDeleteTextures(1, &m_texture);
1171                 m_texture = 0;
1172
1173                 for (GLuint index = 0; index < 8; ++index)
1174                 {
1175                         GLint name;
1176                         glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1177                         if (name != 0)
1178                         {
1179                                 m_context.getTestContext().getLog()
1180                                         << tcu::TestLog::Message << "Binding point " << index
1181                                         << " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1182                                 return ERROR;
1183                         }
1184                 }
1185
1186                 return NO_ERROR;
1187         }
1188
1189         virtual long Cleanup()
1190         {
1191                 glDeleteTextures(1, &m_texture);
1192                 return NO_ERROR;
1193         }
1194 };
1195 //-----------------------------------------------------------------------------
1196 // 1.1.3 BasicAPIBarrier
1197 //-----------------------------------------------------------------------------
1198 class BasicAPIBarrier : public ShaderImageLoadStoreBase
1199 {
1200         virtual long Run()
1201         {
1202                 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1203                 glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1204                 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1205                 glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1206                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1207                 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1208                 glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1209                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1210                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1211                 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1212                 glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1213                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1214
1215                 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1216                                                 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1217                                                 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1218                                                 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1219
1220                 glMemoryBarrier(GL_ALL_BARRIER_BITS);
1221
1222                 return NO_ERROR;
1223         }
1224 };
1225 //-----------------------------------------------------------------------------
1226 // 1.1.4 BasicAPITexParam
1227 //-----------------------------------------------------------------------------
1228 class BasicAPITexParam : public ShaderImageLoadStoreBase
1229 {
1230         GLuint m_texture;
1231
1232         virtual long Setup()
1233         {
1234                 m_texture = 0;
1235                 return NO_ERROR;
1236         }
1237
1238         virtual long Run()
1239         {
1240                 glGenTextures(1, &m_texture);
1241                 glBindTexture(GL_TEXTURE_2D, m_texture);
1242                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1243
1244                 GLint   i;
1245                 GLfloat f;
1246                 GLuint  ui;
1247
1248                 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1249                 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1250                 {
1251                         m_context.getTestContext().getLog()
1252                                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1253                                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1254                                 << tcu::TestLog::EndMessage;
1255                         return ERROR;
1256                 }
1257                 glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1258                 if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1259                 {
1260                         m_context.getTestContext().getLog()
1261                                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1262                                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1263                                 << tcu::TestLog::EndMessage;
1264                         return ERROR;
1265                 }
1266                 glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1267                 if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1268                 {
1269                         m_context.getTestContext().getLog()
1270                                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1271                                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1272                                 << tcu::TestLog::EndMessage;
1273                         return ERROR;
1274                 }
1275                 glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1276                 if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1277                 {
1278                         m_context.getTestContext().getLog()
1279                                 << tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1280                                 << "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1281                                 << tcu::TestLog::EndMessage;
1282                         return ERROR;
1283                 }
1284
1285                 return NO_ERROR;
1286         }
1287
1288         virtual long Cleanup()
1289         {
1290                 glDeleteTextures(1, &m_texture);
1291                 return NO_ERROR;
1292         }
1293 };
1294 //-----------------------------------------------------------------------------
1295 // 1.2.1 BasicAllFormatsStore
1296 //-----------------------------------------------------------------------------
1297 class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1298 {
1299         GLuint m_vao;
1300         GLuint m_vbo;
1301
1302         virtual long Setup()
1303         {
1304                 m_vao = 0;
1305                 m_vbo = 0;
1306                 return NO_ERROR;
1307         }
1308
1309         virtual long Run()
1310         {
1311                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1312
1313                 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1314                         return ERROR;
1315                 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1316                         return ERROR;
1317                 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1318                         return ERROR;
1319
1320                 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1321                         return ERROR;
1322                 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1323                         return ERROR;
1324                 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1325                         return ERROR;
1326
1327                 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1328                         return ERROR;
1329                 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1330                         return ERROR;
1331                 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1332                         return ERROR;
1333
1334                 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1335                         return ERROR;
1336
1337                 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1338                         return ERROR;
1339                 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1340                         return ERROR;
1341                 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1342                         return ERROR;
1343
1344                 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1345                         return ERROR;
1346                 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1347                         return ERROR;
1348                 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1349                         return ERROR;
1350
1351                 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1352                         return ERROR;
1353                 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354                         return ERROR;
1355                 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1356                         return ERROR;
1357                 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1358                         return ERROR;
1359
1360                 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1361                         return ERROR;
1362                 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1363                         return ERROR;
1364                 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1365                         return ERROR;
1366
1367                 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1368                         return ERROR;
1369                 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1370                         return ERROR;
1371                 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1372                         return ERROR;
1373
1374                 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1375                         return ERROR;
1376                 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1377                         return ERROR;
1378                 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1379                         return ERROR;
1380                 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1381                         return ERROR;
1382
1383                 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1384                         return ERROR;
1385                 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1386                         return ERROR;
1387                 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1388                         return ERROR;
1389
1390                 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1391                         return ERROR;
1392                 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1393                         return ERROR;
1394                 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1395                         return ERROR;
1396
1397                 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1398                         return ERROR;
1399                 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1400                         return ERROR;
1401                 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1402                         return ERROR;
1403
1404                 return NO_ERROR;
1405         }
1406
1407         template <typename T>
1408         bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1409         {
1410                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1411                                                          "  gl_Position = i_position;" NL "}";
1412                 const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1413                 const int         kSize   = 16;
1414                 std::vector<T> data(kSize * kSize);
1415                 GLuint             texture;
1416                 glGenTextures(1, &texture);
1417
1418                 for (GLuint unit = 0; unit < 8; ++unit)
1419                 {
1420                         glBindTexture(GL_TEXTURE_2D, texture);
1421                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1422                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1423                         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1424                         glBindTexture(GL_TEXTURE_2D, 0);
1425
1426                         glViewport(0, 0, kSize, kSize);
1427                         glUseProgram(program);
1428                         glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1429                         glBindVertexArray(m_vao);
1430                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1431
1432                         glBindTexture(GL_TEXTURE_2D, texture);
1433                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1434                         glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1435
1436                         for (int i = 0; i < kSize * kSize; ++i)
1437                         {
1438                                 if (!Equal(data[i], expected_value, internalformat))
1439                                 {
1440                                         glDeleteTextures(1, &texture);
1441                                         glUseProgram(0);
1442                                         glDeleteProgram(program);
1443                                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1444                                                                                                                 << ". Value should be: " << ToString(expected_value)
1445                                                                                                                 << ". Format is: " << FormatEnumToString(internalformat)
1446                                                                                                                 << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1447                                         return false;
1448                                 }
1449                         }
1450
1451                         if (unit < 7)
1452                         {
1453                                 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1454                         }
1455                 }
1456
1457                 glDeleteTextures(1, &texture);
1458                 glUseProgram(0);
1459                 glDeleteProgram(program);
1460
1461                 return true;
1462         }
1463
1464         virtual long Cleanup()
1465         {
1466                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1467                 glDeleteVertexArrays(1, &m_vao);
1468                 glDeleteBuffers(1, &m_vbo);
1469                 return NO_ERROR;
1470         }
1471
1472         template <typename T>
1473         std::string GenFS(GLenum internalformat, const T& value)
1474         {
1475                 std::ostringstream os;
1476                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1477                    << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1478                                                                  "  imageStore(g_image, coord, "
1479                    << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1480                 return os.str();
1481         }
1482 };
1483 //-----------------------------------------------------------------------------
1484 // 1.2.2 BasicAllFormatsLoad
1485 //-----------------------------------------------------------------------------
1486 class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1487 {
1488         GLuint m_vao;
1489         GLuint m_vbo;
1490
1491         virtual long Setup()
1492         {
1493                 m_vao = 0;
1494                 m_vbo = 0;
1495                 return NO_ERROR;
1496         }
1497
1498         virtual long Run()
1499         {
1500                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1501
1502                 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1503                         return ERROR;
1504                 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1505                         return ERROR;
1506                 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1507                         return ERROR;
1508
1509                 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1510                         return ERROR;
1511                 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1512                         return ERROR;
1513                 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1514                         return ERROR;
1515
1516                 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1517                         return ERROR;
1518                 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1519                         return ERROR;
1520                 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1521                         return ERROR;
1522
1523                 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1524                         return ERROR;
1525
1526                 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1527                         return ERROR;
1528                 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1529                         return ERROR;
1530                 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1531                         return ERROR;
1532
1533                 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1534                         return ERROR;
1535                 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1536                         return ERROR;
1537                 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1538                         return ERROR;
1539
1540                 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1541                         return ERROR;
1542                 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1543                         return ERROR;
1544                 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1545                         return ERROR;
1546                 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1547                         return ERROR;
1548
1549                 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1550                         return ERROR;
1551                 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1552                         return ERROR;
1553                 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1554                         return ERROR;
1555
1556                 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1557                         return ERROR;
1558                 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1559                         return ERROR;
1560                 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1561                         return ERROR;
1562
1563                 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1564                         return ERROR;
1565                 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1566                         return ERROR;
1567                 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1568                         return ERROR;
1569                 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1570                         return ERROR;
1571
1572                 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1573                         return ERROR;
1574                 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1575                         return ERROR;
1576                 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1577                         return ERROR;
1578
1579                 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1580                         return ERROR;
1581                 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1582                         return ERROR;
1583                 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1584                         return ERROR;
1585
1586                 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1587                         return ERROR;
1588                 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1589                         return ERROR;
1590                 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1591                         return ERROR;
1592
1593                 return NO_ERROR;
1594         }
1595
1596         template <typename T>
1597         bool Read(GLenum internalformat, const T& value, const T& expected_value)
1598         {
1599                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1600                                                          "  gl_Position = i_position;" NL "}";
1601                 const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1602                 const int         kSize   = 16;
1603                 std::vector<T> data(kSize * kSize, value);
1604                 GLuint             texture;
1605                 glGenTextures(1, &texture);
1606
1607                 for (GLuint unit = 0; unit < 8; ++unit)
1608                 {
1609                         glBindTexture(GL_TEXTURE_2D, texture);
1610                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1611                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1612                         glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1613                         glBindTexture(GL_TEXTURE_2D, 0);
1614
1615                         glViewport(0, 0, kSize, kSize);
1616                         glClear(GL_COLOR_BUFFER_BIT);
1617                         glUseProgram(program);
1618                         glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1619                         glBindVertexArray(m_vao);
1620                         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1621
1622                         if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1623                         {
1624                                 glDeleteTextures(1, &texture);
1625                                 glUseProgram(0);
1626                                 glDeleteProgram(program);
1627                                 m_context.getTestContext().getLog()
1628                                         << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1629                                         << ". Unit is: " << unit << tcu::TestLog::EndMessage;
1630                                 return false;
1631                         }
1632
1633                         if (unit < 7)
1634                         {
1635                                 glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1636                         }
1637                 }
1638
1639                 glDeleteTextures(1, &texture);
1640                 glUseProgram(0);
1641                 glDeleteProgram(program);
1642
1643                 return true;
1644         }
1645
1646         virtual long Cleanup()
1647         {
1648                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1649                 glDeleteVertexArrays(1, &m_vao);
1650                 glDeleteBuffers(1, &m_vbo);
1651                 return NO_ERROR;
1652         }
1653
1654         template <typename T>
1655         std::string GenFS(GLenum internalformat, const T& expected_value)
1656         {
1657                 std::ostringstream os;
1658                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1659                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1660                    << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1661                    << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1662                    << expected_value
1663                    << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1664                 return os.str();
1665         }
1666 };
1667 //-----------------------------------------------------------------------------
1668 // 1.2.3 BasicAllFormatsStoreGeometryStages
1669 //-----------------------------------------------------------------------------
1670 class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1671 {
1672         GLuint m_vao;
1673
1674         virtual long Setup()
1675         {
1676                 glGenVertexArrays(1, &m_vao);
1677                 return NO_ERROR;
1678         }
1679
1680         virtual long Run()
1681         {
1682                 if (!SupportedInGeomStages(1))
1683                         return NOT_SUPPORTED;
1684                 glEnable(GL_RASTERIZER_DISCARD);
1685
1686                 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1687                         return ERROR;
1688                 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1689                         return ERROR;
1690                 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1691                         return ERROR;
1692
1693                 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1694                         return ERROR;
1695                 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1696                         return ERROR;
1697                 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1698                         return ERROR;
1699
1700                 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1701                         return ERROR;
1702                 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1703                         return ERROR;
1704                 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1705                         return ERROR;
1706
1707                 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1708                         return ERROR;
1709
1710                 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1711                         return ERROR;
1712                 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1713                         return ERROR;
1714                 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1715                         return ERROR;
1716
1717                 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1718                         return ERROR;
1719                 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1720                         return ERROR;
1721                 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1722                         return ERROR;
1723
1724                 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1725                         return ERROR;
1726                 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1727                         return ERROR;
1728                 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1729                         return ERROR;
1730                 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1731                         return ERROR;
1732
1733                 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1734                         return ERROR;
1735                 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1736                         return ERROR;
1737                 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1738                         return ERROR;
1739
1740                 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1741                         return ERROR;
1742                 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1743                         return ERROR;
1744                 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1745                         return ERROR;
1746
1747                 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1748                         return ERROR;
1749                 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1750                         return ERROR;
1751                 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1752                         return ERROR;
1753                 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1754                         return ERROR;
1755
1756                 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1757                         return ERROR;
1758                 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1759                         return ERROR;
1760                 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1761                         return ERROR;
1762
1763                 if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1764                         return ERROR;
1765                 if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1766                         return ERROR;
1767                 if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1768                         return ERROR;
1769
1770                 if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1771                         return ERROR;
1772                 if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1773                         return ERROR;
1774                 if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1775                         return ERROR;
1776
1777                 return NO_ERROR;
1778         }
1779
1780         template <typename T>
1781         bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1782         {
1783                 const GLuint program =
1784                         BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1785                                                  GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1786                 const int         kSize = 1;
1787                 std::vector<T> data(kSize * kSize);
1788                 GLuint             texture[4];
1789                 glGenTextures(4, texture);
1790
1791                 for (int i = 0; i < 4; ++i)
1792                 {
1793                         glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1794                         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1795                         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1796                         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1797                 }
1798                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1799
1800                 glUseProgram(program);
1801                 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1802                 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1803                 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1804                 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1805                 for (GLuint i = 0; i < 4; ++i)
1806                 {
1807                         glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1808                 }
1809                 glBindVertexArray(m_vao);
1810                 glPatchParameteri(GL_PATCH_VERTICES, 1);
1811                 glDrawArrays(GL_PATCHES, 0, 1);
1812                 glPatchParameteri(GL_PATCH_VERTICES, 3);
1813
1814                 for (int i = 0; i < 4; ++i)
1815                 {
1816                         glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1817                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1818                         glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1819
1820                         if (!Equal(data[0], expected_value, internalformat))
1821                         {
1822                                 glDeleteTextures(4, texture);
1823                                 glUseProgram(0);
1824                                 glDeleteProgram(program);
1825                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1826                                                                                                         << ". Value should be: " << ToString(expected_value)
1827                                                                                                         << ". Format is: " << FormatEnumToString(internalformat)
1828                                                                                                         << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1829                                 return false;
1830                         }
1831                 }
1832                 glDeleteTextures(4, texture);
1833                 glUseProgram(0);
1834                 glDeleteProgram(program);
1835                 return true;
1836         }
1837
1838         virtual long Cleanup()
1839         {
1840                 glDisable(GL_RASTERIZER_DISCARD);
1841                 glDeleteVertexArrays(1, &m_vao);
1842                 return NO_ERROR;
1843         }
1844
1845         template <typename T>
1846         std::string GenVS(GLenum internalformat, const T& value)
1847         {
1848                 std::ostringstream os;
1849                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1850                    << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1851                                                                  "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  imageStore(g_image0, coord, "
1852                    << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1853                 return os.str();
1854         }
1855
1856         template <typename T>
1857         std::string GenTCS(GLenum internalformat, const T& value)
1858         {
1859                 std::ostringstream os;
1860                 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1861                    << ") writeonly uniform " << TypePrefix<T>()
1862                    << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1863                           "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1864                           "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1865                           "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1866                    << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1867                 return os.str();
1868         }
1869
1870         template <typename T>
1871         std::string GenTES(GLenum internalformat, const T& value)
1872         {
1873                 std::ostringstream os;
1874                 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1875                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1876                    << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1877                           "  imageStore(g_image2, coord, "
1878                    << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1879                 return os.str();
1880         }
1881
1882         template <typename T>
1883         std::string GenGS(GLenum internalformat, const T& value)
1884         {
1885                 std::ostringstream os;
1886                 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1887                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1888                    << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1889                           "  imageStore(g_image3, coord, "
1890                    << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1891                 return os.str();
1892         }
1893 };
1894 //-----------------------------------------------------------------------------
1895 // 1.2.4 BasicAllFormatsLoadGeometryStages
1896 //-----------------------------------------------------------------------------
1897 class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1898 {
1899         GLuint m_vao;
1900
1901         virtual long Setup()
1902         {
1903                 glGenVertexArrays(1, &m_vao);
1904                 return NO_ERROR;
1905         }
1906
1907         virtual long Run()
1908         {
1909                 if (!SupportedInGeomStages(2))
1910                         return NOT_SUPPORTED;
1911                 glEnable(GL_RASTERIZER_DISCARD);
1912
1913                 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1914                         return ERROR;
1915                 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1916                         return ERROR;
1917                 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1918                         return ERROR;
1919
1920                 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1921                         return ERROR;
1922                 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1923                         return ERROR;
1924                 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1925                         return ERROR;
1926
1927                 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1928                         return ERROR;
1929                 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1930                         return ERROR;
1931                 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1932                         return ERROR;
1933
1934                 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1935                         return ERROR;
1936
1937                 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1938                         return ERROR;
1939                 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1940                         return ERROR;
1941                 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1942                         return ERROR;
1943
1944                 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1945                         return ERROR;
1946                 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1947                         return ERROR;
1948                 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1949                         return ERROR;
1950
1951                 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1952                         return ERROR;
1953                 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1954                         return ERROR;
1955                 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1956                         return ERROR;
1957                 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1958                         return ERROR;
1959
1960                 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1961                         return ERROR;
1962                 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1963                         return ERROR;
1964                 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1965                         return ERROR;
1966
1967                 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1968                         return ERROR;
1969                 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1970                         return ERROR;
1971                 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1972                         return ERROR;
1973
1974                 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1975                         return ERROR;
1976                 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1977                         return ERROR;
1978                 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1979                         return ERROR;
1980                 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1981                         return ERROR;
1982
1983                 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1984                         return ERROR;
1985                 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1986                         return ERROR;
1987                 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1988                         return ERROR;
1989
1990                 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1991                         return ERROR;
1992                 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1993                         return ERROR;
1994                 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1995                         return ERROR;
1996
1997                 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1998                         return ERROR;
1999                 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2000                         return ERROR;
2001                 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2002                         return ERROR;
2003
2004                 return NO_ERROR;
2005         }
2006
2007         template <typename T>
2008         bool Read(GLenum internalformat, const T& value, const T& expected_value)
2009         {
2010                 const GLuint program = BuildProgram(
2011                         GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2012                         GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2013                 const int         kSize = 1;
2014                 std::vector<T> data(kSize * kSize, value);
2015                 GLuint             texture[8];
2016                 glGenTextures(8, texture);
2017
2018                 for (int i = 0; i < 4; ++i)
2019                 {
2020                         glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2021                         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2022                         glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2023                         glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2024                 }
2025                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2026                 vec4 zero(0);
2027                 for (int i = 4; i < 8; ++i)
2028                 {
2029                         glBindTexture(GL_TEXTURE_2D, texture[i]);
2030                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2031                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2032                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2033                 }
2034                 glBindTexture(GL_TEXTURE_2D, 0);
2035
2036                 glUseProgram(program);
2037                 glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2038                 glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2039                 glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2040                 glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2041                 glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2042                 glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2043                 glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2044                 glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2045
2046                 for (GLuint i = 0; i < 4; ++i)
2047                 {
2048                         glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2049                 }
2050                 for (GLuint i = 4; i < 8; ++i)
2051                 {
2052                         glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2053                 }
2054                 glBindVertexArray(m_vao);
2055                 glPatchParameteri(GL_PATCH_VERTICES, 1);
2056                 glDrawArrays(GL_PATCHES, 0, 1);
2057                 glPatchParameteri(GL_PATCH_VERTICES, 3);
2058
2059                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2060                 const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
2061                 vec4                                     g_color_eps  = vec4(
2062                         1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2063                         1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2064
2065                 for (int i = 0; i < 4; ++i)
2066                 {
2067                         glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2068                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2069                         vec4 result;
2070                         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2071                         if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2072                         {
2073                                 glDeleteTextures(8, texture);
2074                                 glUseProgram(0);
2075                                 glDeleteProgram(program);
2076                                 m_context.getTestContext().getLog()
2077                                         << tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2078                                         << ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2079                                 return false;
2080                         }
2081                 }
2082                 glDeleteTextures(8, texture);
2083                 glUseProgram(0);
2084                 glDeleteProgram(program);
2085                 return true;
2086         }
2087
2088         virtual long Cleanup()
2089         {
2090                 glDisable(GL_RASTERIZER_DISCARD);
2091                 glDeleteVertexArrays(1, &m_vao);
2092                 return NO_ERROR;
2093         }
2094
2095         template <typename T>
2096         std::string GenVS(GLenum internalformat, const T& expected_value)
2097         {
2098                 std::ostringstream os;
2099                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2100                    << TypePrefix<T>()
2101                    << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2102                           "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2103                    << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2104                    << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2105                                                                 "  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2106                 return os.str();
2107         }
2108
2109         template <typename T>
2110         std::string GenTCS(GLenum internalformat, const T& expected_value)
2111         {
2112                 std::ostringstream os;
2113                 os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2114                    << ") readonly uniform " << TypePrefix<T>()
2115                    << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2116                           "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2117                           "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2118                           "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2119                    << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2120                    << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2121                                                                 "  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2122                 return os.str();
2123         }
2124
2125         template <typename T>
2126         std::string GenTES(GLenum internalformat, const T& expected_value)
2127         {
2128                 std::ostringstream os;
2129                 os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2130                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2131                    << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2132                           "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2133                    << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2134                    << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2135                                                                 "  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2136                 return os.str();
2137         }
2138
2139         template <typename T>
2140         std::string GenGS(GLenum internalformat, const T& expected_value)
2141         {
2142                 std::ostringstream os;
2143                 os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2144                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2145                    << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2146                           "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2147                    << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2148                    << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2149                                                                 "  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2150                 return os.str();
2151         }
2152 };
2153 //-----------------------------------------------------------------------------
2154 // 1.2.5 BasicAllFormatsLoadStoreComputeStage
2155 //-----------------------------------------------------------------------------
2156 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2157 {
2158         virtual long Run()
2159         {
2160                 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2161                 {
2162                         m_context.getTestContext().getLog()
2163                                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2164                                 << tcu::TestLog::EndMessage;
2165                         return NOT_SUPPORTED;
2166                 }
2167
2168                 if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2169                         return ERROR;
2170                 if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2171                         return ERROR;
2172                 if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2173                         return ERROR;
2174
2175                 if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2176                         return ERROR;
2177                 if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2178                         return ERROR;
2179                 if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2180                         return ERROR;
2181
2182                 if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2183                         return ERROR;
2184                 if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2185                         return ERROR;
2186                 if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2187                         return ERROR;
2188
2189                 if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2190                         return ERROR;
2191
2192                 if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2193                         return ERROR;
2194                 if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2195                         return ERROR;
2196                 if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2197                         return ERROR;
2198
2199                 if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2200                         return ERROR;
2201                 if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2202                         return ERROR;
2203                 if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2204                         return ERROR;
2205
2206                 if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2207                         return ERROR;
2208                 if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2209                         return ERROR;
2210                 if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2211                         return ERROR;
2212                 if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2213                         return ERROR;
2214
2215                 if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2216                         return ERROR;
2217                 if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2218                         return ERROR;
2219                 if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2220                         return ERROR;
2221
2222                 if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2223                         return ERROR;
2224                 if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2225                         return ERROR;
2226                 if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2227                         return ERROR;
2228
2229                 if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2230                         return ERROR;
2231                 if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2232                         return ERROR;
2233                 if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2234                         return ERROR;
2235                 if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2236                         return ERROR;
2237
2238                 if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2239                         return ERROR;
2240                 if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2241                         return ERROR;
2242                 if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2243                         return ERROR;
2244
2245                 if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2246                         return ERROR;
2247                 if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2248                         return ERROR;
2249                 if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2250                         return ERROR;
2251
2252                 if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2253                         return ERROR;
2254                 if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2255                         return ERROR;
2256                 if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2257                         return ERROR;
2258
2259                 return NO_ERROR;
2260         }
2261
2262         template <typename T>
2263         bool Read(GLenum internalformat, const T& value, const T& expected_value)
2264         {
2265                 GLuint                    program;
2266                 std::string               source = GenCS<T>(internalformat);
2267                 const char* const src   = source.c_str();
2268                 GLuint                    sh     = glCreateShader(GL_COMPUTE_SHADER);
2269                 glShaderSource(sh, 1, &src, NULL);
2270                 glCompileShader(sh);
2271                 program = glCreateProgram();
2272                 glAttachShader(program, sh);
2273                 glLinkProgram(program);
2274                 glDeleteShader(sh);
2275
2276                 const int         kSize = 1;
2277                 std::vector<T> data(kSize * kSize, value);
2278                 GLuint             texture[2];
2279                 glGenTextures(2, texture);
2280
2281                 glBindTexture(GL_TEXTURE_2D, texture[0]);
2282                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2283                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2284                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2285                 glBindTexture(GL_TEXTURE_2D, texture[1]);
2286                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2287                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2288                 vec4 zero(0);
2289                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2290
2291                 glBindTexture(GL_TEXTURE_2D, 0);
2292
2293                 glUseProgram(program);
2294                 glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2295                 glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2296
2297                 glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2298                 glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2299
2300                 glDispatchCompute(1, 1, 1);
2301
2302                 for (int i = 0; i < 2; ++i)
2303                 {
2304                         glBindTexture(GL_TEXTURE_2D, texture[i]);
2305                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2306                         glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2307
2308                         if (!Equal(data[0], expected_value, internalformat))
2309                         {
2310                                 glDeleteTextures(4, texture);
2311                                 glUseProgram(0);
2312                                 glDeleteProgram(program);
2313                                 m_context.getTestContext().getLog()
2314                                         << tcu::TestLog::Message << "Value is: " << ToString(data[0])
2315                                         << ". Value should be: " << ToString(expected_value)
2316                                         << ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2317                                 return false;
2318                         }
2319                 }
2320                 glDeleteTextures(2, texture);
2321                 glUseProgram(0);
2322                 glDeleteProgram(program);
2323                 return true;
2324         }
2325
2326         template <typename T>
2327         std::string GenCS(GLenum internalformat)
2328         {
2329                 std::ostringstream os;
2330                 os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2331                           "layout("
2332                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2333                    << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2334                    << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2335                                                                  "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2336                    << TypePrefix<T>()
2337                    << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2338                 return os.str();
2339         }
2340 };
2341 //-----------------------------------------------------------------------------
2342 // 1.3.1 BasicAllTargetsStore
2343 //-----------------------------------------------------------------------------
2344 class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2345 {
2346         GLuint m_vao;
2347         GLuint m_vbo;
2348
2349         virtual long Setup()
2350         {
2351                 m_vao = 0;
2352                 m_vbo = 0;
2353                 return NO_ERROR;
2354         }
2355
2356         virtual long Run()
2357         {
2358                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2359
2360                 if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2361                         return ERROR;
2362                 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2363                         return ERROR;
2364                 if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2365                         return ERROR;
2366
2367                 if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2368                         return ERROR;
2369                 if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2370                         return ERROR;
2371                 if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2372                         return ERROR;
2373
2374                 if (SupportedSamples(4))
2375                 {
2376                         if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2377                                 return ERROR;
2378
2379                         GLint isamples;
2380                         glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2381                         if (isamples >= 4)
2382                         {
2383                                 if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2384                                         return ERROR;
2385                                 if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2386                                         return ERROR;
2387                         }
2388                 }
2389                 return NO_ERROR;
2390         }
2391
2392         virtual long Cleanup()
2393         {
2394                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2395                 glDeleteVertexArrays(1, &m_vao);
2396                 glDeleteBuffers(1, &m_vbo);
2397                 return NO_ERROR;
2398         }
2399
2400         template <typename T>
2401         bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2402         {
2403                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2404                                                          "  gl_Position = i_position;" NL "}";
2405                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2406                 GLuint           textures[8];
2407                 GLuint           buffer;
2408                 glGenTextures(8, textures);
2409                 glGenBuffers(1, &buffer);
2410
2411                 const int         kSize = 16;
2412                 std::vector<T> data(kSize * kSize * 2);
2413
2414                 glBindTexture(GL_TEXTURE_1D, textures[0]);
2415                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2416                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2417                 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2418                 glBindTexture(GL_TEXTURE_1D, 0);
2419
2420                 glBindTexture(GL_TEXTURE_2D, textures[1]);
2421                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2422                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2423                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2424                 glBindTexture(GL_TEXTURE_2D, 0);
2425
2426                 glBindTexture(GL_TEXTURE_3D, textures[2]);
2427                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2428                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2429                 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2430                 glBindTexture(GL_TEXTURE_3D, 0);
2431
2432                 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2433                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2434                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2435                 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2436                 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2437
2438                 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2439                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2440                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2441                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2442                                          &data[0]);
2443                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2444                                          &data[0]);
2445                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2446                                          &data[0]);
2447                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2448                                          &data[0]);
2449                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2450                                          &data[0]);
2451                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2452                                          &data[0]);
2453                 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2454
2455                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2456                 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2457                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2458                 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2459                 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2460                 glBindTexture(GL_TEXTURE_BUFFER, 0);
2461
2462                 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2463                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2464                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2465                 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2466                 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2467
2468                 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2469                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2470                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2471                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2472                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2473
2474                 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475                 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2476                 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2477                 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2478                 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2479                 glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2480                 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481                 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2482
2483                 glUseProgram(program);
2484                 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2485                 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2486                 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2487                 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2488                 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2489                 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2490                 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2491                 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2492
2493                 glBindVertexArray(m_vao);
2494                 glViewport(0, 0, kSize, kSize);
2495                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2496
2497                 bool status = true;
2498
2499                 glBindTexture(GL_TEXTURE_1D, textures[0]);
2500                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2501                 glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2502                 glBindTexture(GL_TEXTURE_1D, 0);
2503                 for (int i = 0; i < kSize; ++i)
2504                 {
2505                         if (!tcu::allEqual(data[i], expected_value))
2506                         {
2507                                 status = false;
2508                                 m_context.getTestContext().getLog()
2509                                         << tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2510                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2511                                 break;
2512                         }
2513                 }
2514                 std::fill(data.begin(), data.end(), T(0));
2515
2516                 glBindTexture(GL_TEXTURE_2D, textures[1]);
2517                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2518                 glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2519                 glBindTexture(GL_TEXTURE_2D, 0);
2520                 for (int i = 0; i < kSize * kSize; ++i)
2521                 {
2522                         if (!tcu::allEqual(data[i], expected_value))
2523                         {
2524                                 status = false;
2525                                 m_context.getTestContext().getLog()
2526                                         << tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2527                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2528                                 break;
2529                         }
2530                 }
2531
2532                 glBindTexture(GL_TEXTURE_3D, textures[2]);
2533                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2534                 glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2535                 glBindTexture(GL_TEXTURE_3D, 0);
2536                 for (int i = 0; i < kSize * kSize * 2; ++i)
2537                 {
2538                         if (!tcu::allEqual(data[i], expected_value))
2539                         {
2540                                 status = false;
2541                                 m_context.getTestContext().getLog()
2542                                         << tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2543                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2544                                 break;
2545                         }
2546                 }
2547
2548                 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2549                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2550                 glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2551                 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2552                 for (int i = 0; i < kSize * kSize; ++i)
2553                 {
2554                         if (!tcu::allEqual(data[i], expected_value))
2555                         {
2556                                 status = false;
2557                                 m_context.getTestContext().getLog()
2558                                         << tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2559                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2560                                 break;
2561                         }
2562                 }
2563
2564                 {
2565                         glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2566                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2567                         for (int face = 0; face < 6; ++face)
2568                         {
2569                                 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2570                                 for (int i = 0; i < kSize * kSize; ++i)
2571                                 {
2572                                         if (!tcu::allEqual(data[i], expected_value))
2573                                         {
2574                                                 status = false;
2575                                                 m_context.getTestContext().getLog()
2576                                                         << tcu::TestLog::Message
2577                                                         << "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2578                                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2579                                                 break;
2580                                         }
2581                                 }
2582                         }
2583                         glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2584                 }
2585
2586                 glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2587                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2588                 glBindTexture(GL_TEXTURE_BUFFER, 0);
2589                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2590                 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2591                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2592                 for (int i = 0; i < kSize; ++i)
2593                 {
2594                         if (!tcu::allEqual(data[i], expected_value))
2595                         {
2596                                 status = false;
2597                                 m_context.getTestContext().getLog()
2598                                         << tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2599                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2600                                 break;
2601                         }
2602                 }
2603
2604                 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2605                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2606                 glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2607                 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2608                 for (int i = 0; i < kSize * 2; ++i)
2609                 {
2610                         if (!tcu::allEqual(data[i], expected_value))
2611                         {
2612                                 status = false;
2613                                 m_context.getTestContext().getLog()
2614                                         << tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2615                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2616                                 break;
2617                         }
2618                 }
2619
2620                 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2621                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2622                 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2623                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2624                 for (int i = 0; i < kSize * kSize * 2; ++i)
2625                 {
2626                         if (!tcu::allEqual(data[i], expected_value))
2627                         {
2628                                 status = false;
2629                                 m_context.getTestContext().getLog()
2630                                         << tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2631                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2632                                 break;
2633                         }
2634                 }
2635
2636                 glUseProgram(0);
2637                 glDeleteProgram(program);
2638                 glDeleteTextures(8, textures);
2639                 glDeleteBuffers(1, &buffer);
2640
2641                 return status;
2642         }
2643
2644         template <typename T>
2645         bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2646         {
2647
2648                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2649                                                          "  gl_Position = i_position;" NL "}";
2650                 const GLuint program     = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2651                 const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2652                 GLuint           textures[2];
2653                 glGenTextures(2, textures);
2654
2655                 const int kSize = 16;
2656
2657                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2658                 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2659                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2660
2661                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2662                 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2663                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2664
2665                 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2666                 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2667
2668                 glClear(GL_COLOR_BUFFER_BIT);
2669                 glUseProgram(program);
2670                 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2671                 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2672
2673                 glBindVertexArray(m_vao);
2674                 glViewport(0, 0, kSize, kSize);
2675                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2676
2677                 bool status = true;
2678
2679                 glActiveTexture(GL_TEXTURE0);
2680                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2681                 glActiveTexture(GL_TEXTURE1);
2682                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2683
2684                 glUseProgram(val_program);
2685                 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2686                 glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2687
2688                 glBindVertexArray(m_vao);
2689                 glViewport(0, 0, kSize, kSize);
2690                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2691                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2692
2693                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2694                 {
2695                         status = false;
2696                         m_context.getTestContext().getLog()
2697                                 << tcu::TestLog::Message
2698                                 << "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2699                                 << tcu::TestLog::EndMessage;
2700                 }
2701
2702                 glActiveTexture(GL_TEXTURE0);
2703                 glDeleteTextures(2, textures);
2704                 glUseProgram(0);
2705                 glDeleteProgram(program);
2706                 glDeleteProgram(val_program);
2707
2708                 return status;
2709         }
2710
2711         template <typename T>
2712         bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2713         {
2714                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2715                                                          "  gl_Position = i_position;" NL "}";
2716                 const GLuint program =
2717                         BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2718                 GLuint textures[1];
2719                 glGenTextures(1, textures);
2720
2721                 const int kSize = 16;
2722
2723                 std::vector<T> data(kSize * kSize * 12);
2724                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2725                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2726                 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2727                                          &data[0]);
2728                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2729
2730                 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2731
2732                 glUseProgram(program);
2733                 glBindVertexArray(m_vao);
2734                 glViewport(0, 0, kSize, kSize);
2735                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2736
2737                 bool status = true;
2738
2739                 std::fill(data.begin(), data.end(), T(0));
2740                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2741                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2742                 glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2743                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2744                 for (int i = 0; i < kSize * kSize * 12; ++i)
2745                 {
2746                         if (!tcu::allEqual(data[i], expected_value))
2747                         {
2748                                 status = false;
2749                                 m_context.getTestContext().getLog()
2750                                         << tcu::TestLog::Message
2751                                         << "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2752                                         << ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2753                                 break;
2754                         }
2755                 }
2756
2757                 glDeleteTextures(1, textures);
2758                 glUseProgram(0);
2759                 glDeleteProgram(program);
2760
2761                 return status;
2762         }
2763
2764         template <typename T>
2765         std::string GenFS(GLenum internalformat, const T& write_value)
2766         {
2767                 std::ostringstream os;
2768                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2769                    << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2770                    << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2771                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2772                    << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2773                    << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2774                    << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2775                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2776                    << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2777                    << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2778                    << ") writeonly uniform " << TypePrefix<T>()
2779                    << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2780                           "  imageStore(g_image_1d, coord.x, "
2781                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2782                    << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2783                    << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2784                    << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2785                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2786                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2787                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2788                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2789                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2790                    << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2791                    << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2792                    << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2793                    << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2794                    << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2795                    << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2796                    << write_value << ");" NL "  discard;" NL "}";
2797                 return os.str();
2798         }
2799
2800         template <typename T>
2801         std::string GenFSMS(GLenum internalformat, const T& write_value)
2802         {
2803                 std::ostringstream os;
2804                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2805                    << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2806                    << ") writeonly uniform " << TypePrefix<T>()
2807                    << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2808                           "  imageStore(g_image_2dms, coord, 0, "
2809                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2810                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2811                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2812                    << TypePrefix<T>() << "vec4" << write_value
2813                    << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2814                    << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2815                    << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2816                    << TypePrefix<T>() << "vec4" << write_value
2817                    << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2818                    << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2819                    << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2820                    << TypePrefix<T>() << "vec4" << write_value
2821                    << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2822                    << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2823                    << "vec4" << write_value << ");" NL "  discard;" NL "}";
2824                 return os.str();
2825         }
2826
2827         template <typename T>
2828         std::string GenFSMSVal(const T& expected_value)
2829         {
2830                 std::ostringstream os;
2831                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2832                    << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2833                    << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2834                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2835                    << TypePrefix<T>() << "vec4" << expected_value
2836                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2837                    << TypePrefix<T>() << "vec4" << expected_value
2838                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2839                    << TypePrefix<T>() << "vec4" << expected_value
2840                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2841                    << TypePrefix<T>() << "vec4" << expected_value
2842                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2843                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2844                    << TypePrefix<T>() << "vec4" << expected_value
2845                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2846                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2847                    << TypePrefix<T>() << "vec4" << expected_value
2848                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2849                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2850                    << TypePrefix<T>() << "vec4" << expected_value
2851                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2852                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2853                    << TypePrefix<T>() << "vec4" << expected_value
2854                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2855                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2856                    << TypePrefix<T>() << "vec4" << expected_value
2857                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2858                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2859                    << TypePrefix<T>() << "vec4" << expected_value
2860                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2861                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2862                    << TypePrefix<T>() << "vec4" << expected_value
2863                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2864                           "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2865                    << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2866                 return os.str();
2867         }
2868
2869         template <typename T>
2870         std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2871         {
2872                 std::ostringstream os;
2873                 os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2874                    << TypePrefix<T>()
2875                    << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2876                           "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2877                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2878                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2879                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2880                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2881                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2882                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2883                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2884                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2885                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2886                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2887                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2888                    << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2889                 return os.str();
2890         }
2891 };
2892 //-----------------------------------------------------------------------------
2893 // 1.3.2.1 BasicAllTargetsLoadNonMS
2894 //-----------------------------------------------------------------------------
2895 class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2896 {
2897         GLuint m_vao;
2898         GLuint m_vbo;
2899
2900         virtual long Setup()
2901         {
2902                 m_vao = 0;
2903                 m_vbo = 0;
2904                 return NO_ERROR;
2905         }
2906
2907         virtual long Run()
2908         {
2909                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2910
2911                 if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2912                         return ERROR;
2913                 if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2914                         return ERROR;
2915                 if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2916                         return ERROR;
2917
2918                 if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2919                         return ERROR;
2920                 if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2921                         return ERROR;
2922                 if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2923                         return ERROR;
2924
2925                 return NO_ERROR;
2926         }
2927
2928         virtual long Cleanup()
2929         {
2930                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2931                 glDeleteVertexArrays(1, &m_vao);
2932                 glDeleteBuffers(1, &m_vbo);
2933                 return NO_ERROR;
2934         }
2935
2936         template <typename T>
2937         bool Read(GLenum internalformat, const T& value, const T& expected_value)
2938         {
2939                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2940                                                          "  gl_Position = i_position;" NL "}";
2941                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2942                 GLuint           textures[7];
2943                 GLuint           buffer;
2944                 glGenTextures(7, textures);
2945                 glGenBuffers(1, &buffer);
2946
2947                 const int         kSize = 16;
2948                 std::vector<T> data(kSize * kSize * 2, value);
2949
2950                 glBindTexture(GL_TEXTURE_1D, textures[0]);
2951                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2952                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2953                 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2954                 glBindTexture(GL_TEXTURE_1D, 0);
2955
2956                 glBindTexture(GL_TEXTURE_2D, textures[1]);
2957                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2958                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2959                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2960                 glBindTexture(GL_TEXTURE_2D, 0);
2961
2962                 glBindTexture(GL_TEXTURE_3D, textures[2]);
2963                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2964                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2965                 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2966                 glBindTexture(GL_TEXTURE_3D, 0);
2967
2968                 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2969                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2970                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2971                 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2972                 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2973
2974                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2975                 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2976                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
2977                 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2978                 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2979                 glBindTexture(GL_TEXTURE_BUFFER, 0);
2980
2981                 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2982                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2983                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2984                 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2985                 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2986
2987                 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2988                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2989                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2990                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2991                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2992
2993                 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994                 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2995                 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2996                 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997                 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2998                 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999                 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3000
3001                 glClear(GL_COLOR_BUFFER_BIT);
3002
3003                 glUseProgram(program);
3004                 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3005                 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3006                 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3007                 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3008                 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3009                 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3010                 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3011
3012                 glBindVertexArray(m_vao);
3013                 glViewport(0, 0, kSize, kSize);
3014                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3015
3016                 bool status = true;
3017
3018                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3019                 {
3020                         status = false;
3021                 }
3022
3023                 std::map<std::string, GLuint> name_index_map;
3024                 GLint uniforms;
3025                 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3026                 if (uniforms != 7)
3027                 {
3028                         status = false;
3029                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3030                                                                                                 << " should be 7." << tcu::TestLog::EndMessage;
3031                 }
3032                 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3033                 {
3034                         GLchar name[32];
3035                         glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3036                         name_index_map.insert(std::make_pair(std::string(name), index));
3037                 }
3038
3039                 if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3040                         status = false;
3041                 if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3042                         status = false;
3043                 if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3044                         status = false;
3045                 if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3046                         status = false;
3047                 if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3048                         status = false;
3049                 if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3050                         status = false;
3051                 if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3052                         status = false;
3053
3054                 glUseProgram(0);
3055                 glDeleteProgram(program);
3056                 glDeleteTextures(7, textures);
3057                 glDeleteBuffers(1, &buffer);
3058
3059                 return status;
3060         }
3061
3062         template <typename T>
3063         bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3064         {
3065                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3066                                                          "  gl_Position = i_position;" NL "}";
3067                 const GLuint program =
3068                         BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3069                 GLuint textures[2];
3070                 glGenTextures(2, textures);
3071
3072                 const int         kSize = 16;
3073                 std::vector<T> data(kSize * kSize * 12, value);
3074
3075                 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3076                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3077                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3078                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3079                                          &data[0]);
3080                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3081                                          &data[0]);
3082                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3083                                          &data[0]);
3084                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3085                                          &data[0]);
3086                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3087                                          &data[0]);
3088                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3089                                          &data[0]);
3090                 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3091
3092                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3093                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3094                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3095                 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3096                                          &data[0]);
3097                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3098
3099                 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100                 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3101
3102                 glClear(GL_COLOR_BUFFER_BIT);
3103
3104                 glUseProgram(program);
3105                 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3106                 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3107
3108                 glBindVertexArray(m_vao);
3109                 glViewport(0, 0, kSize, kSize);
3110                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3111
3112                 bool status = true;
3113
3114                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3115                 {
3116                         status = false;
3117                 }
3118
3119                 std::map<std::string, GLuint> name_index_map;
3120                 GLint uniforms;
3121                 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3122                 if (uniforms != 2)
3123                 {
3124                         status = false;
3125                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3126                                                                                                 << " should be 2." << tcu::TestLog::EndMessage;
3127                 }
3128                 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3129                 {
3130                         GLchar name[32];
3131                         glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3132                         name_index_map.insert(std::make_pair(std::string(name), index));
3133                 }
3134
3135                 if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3136                         status = false;
3137                 if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3138                         status = false;
3139
3140                 glUseProgram(0);
3141                 glDeleteProgram(program);
3142                 glDeleteTextures(2, textures);
3143
3144                 return status;
3145         }
3146
3147         template <typename T>
3148         std::string GenFS(GLenum internalformat, const T& expected_value)
3149         {
3150                 std::ostringstream os;
3151                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3152                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3153                    << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3154                    << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3155                    << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3156                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3157                    << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3158                    << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3159                    << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3160                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3161                    << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3162                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3163                    << TypePrefix<T>()
3164                    << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3165                    << expected_value
3166                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3167                    << TypePrefix<T>() << "vec4" << expected_value
3168                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3169                           "  if (v != "
3170                    << TypePrefix<T>() << "vec4" << expected_value
3171                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3172                           "  if (v != "
3173                    << TypePrefix<T>() << "vec4" << expected_value
3174                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3175                    << TypePrefix<T>() << "vec4" << expected_value
3176                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3177                    << TypePrefix<T>() << "vec4" << expected_value
3178                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3179                           "  if (v != "
3180                    << TypePrefix<T>() << "vec4" << expected_value
3181                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3182                           "  if (v != "
3183                    << TypePrefix<T>() << "vec4" << expected_value
3184                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3185                           "  if (v != "
3186                    << TypePrefix<T>() << "vec4" << expected_value
3187                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3188                           "  if (v != "
3189                    << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3190                 return os.str();
3191         }
3192
3193         template <typename T>
3194         std::string GenFSCube(GLenum internalformat, const T& expected_value)
3195         {
3196                 std::ostringstream os;
3197                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3198                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3199                    << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3200                    << TypePrefix<T>()
3201                    << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3202                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3203                    << TypePrefix<T>()
3204                    << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3205                    << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3206                                                                                   "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  if (v != "
3207                    << TypePrefix<T>() << "vec4" << expected_value
3208                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3209                           "  if (v != "
3210                    << TypePrefix<T>() << "vec4" << expected_value
3211                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3212                           "  if (v != "
3213                    << TypePrefix<T>() << "vec4" << expected_value
3214                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3215                           "  if (v != "
3216                    << TypePrefix<T>() << "vec4" << expected_value
3217                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3218                           "  if (v != "
3219                    << TypePrefix<T>() << "vec4" << expected_value
3220                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3221                           "  if (v != "
3222                    << TypePrefix<T>() << "vec4" << expected_value
3223                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3224                           "  if (v != "
3225                    << TypePrefix<T>() << "vec4" << expected_value
3226                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3227                           "  if (v != "
3228                    << TypePrefix<T>() << "vec4" << expected_value
3229                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3230                           "  if (v != "
3231                    << TypePrefix<T>() << "vec4" << expected_value
3232                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3233                           "  if (v != "
3234                    << TypePrefix<T>() << "vec4" << expected_value
3235                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3236                           "  if (v != "
3237                    << TypePrefix<T>() << "vec4" << expected_value
3238                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3239                           "  if (v != "
3240                    << TypePrefix<T>() << "vec4" << expected_value
3241                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3242                           "  if (v != "
3243                    << TypePrefix<T>() << "vec4" << expected_value
3244                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3245                           "  if (v != "
3246                    << TypePrefix<T>() << "vec4" << expected_value
3247                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3248                           "  if (v != "
3249                    << TypePrefix<T>() << "vec4" << expected_value
3250                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3251                           "  if (v != "
3252                    << TypePrefix<T>() << "vec4" << expected_value
3253                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3254                           "  if (v != "
3255                    << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3256                 return os.str();
3257         }
3258 };
3259 //-----------------------------------------------------------------------------
3260 // 1.3.2.2 BasicAllTargetsLoadMS
3261 //-----------------------------------------------------------------------------
3262 class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3263 {
3264         GLuint m_vao;
3265         GLuint m_vbo;
3266
3267         virtual long Setup()
3268         {
3269                 m_vao = 0;
3270                 m_vbo = 0;
3271                 return NO_ERROR;
3272         }
3273
3274         virtual long Run()
3275         {
3276                 if (!SupportedSamples(4))
3277                         return NOT_SUPPORTED;
3278
3279                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3280
3281                 if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3282                         return ERROR;
3283
3284                 GLint isamples;
3285                 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3286                 if (isamples >= 4)
3287                 {
3288                         if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3289                                 return ERROR;
3290                         if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3291                                 return ERROR;
3292                 }
3293
3294                 return NO_ERROR;
3295         }
3296
3297         virtual long Cleanup()
3298         {
3299                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3300                 glDeleteVertexArrays(1, &m_vao);
3301                 glDeleteBuffers(1, &m_vbo);
3302                 return NO_ERROR;
3303         }
3304
3305         template <typename T>
3306         bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3307         {
3308                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3309                                                          "  gl_Position = i_position;" NL "}";
3310                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3311                 GLuint           textures[2];
3312                 glGenTextures(2, textures);
3313
3314                 const int kSize = 16;
3315
3316                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3317                 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3318                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3319
3320                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3321                 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3322                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3323
3324                 GLuint fbo;
3325                 glGenFramebuffers(1, &fbo);
3326                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3327                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3328                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3329                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3330                 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3331                 glDrawBuffers(3, draw_buffers);
3332                 ClearBuffer(GL_COLOR, 0, value);
3333                 ClearBuffer(GL_COLOR, 1, value);
3334                 ClearBuffer(GL_COLOR, 2, value);
3335                 glDeleteFramebuffers(1, &fbo);
3336
3337                 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3338                 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3339
3340                 glUseProgram(program);
3341                 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3342                 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3343
3344                 glClear(GL_COLOR_BUFFER_BIT);
3345                 glBindVertexArray(m_vao);
3346                 glViewport(0, 0, kSize, kSize);
3347                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3348
3349                 bool status = true;
3350
3351                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3352                 {
3353                         status = false;
3354                 }
3355
3356                 std::map<std::string, GLuint> name_index_map;
3357                 GLint uniforms;
3358                 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3359                 if (uniforms != 2)
3360                 {
3361                         status = false;
3362                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3363                                                                                                 << " should be 2." << tcu::TestLog::EndMessage;
3364                 }
3365                 for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3366                 {
3367                         GLchar name[32];
3368                         glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3369                         name_index_map.insert(std::make_pair(std::string(name), index));
3370                 }
3371
3372                 if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3373                         status = false;
3374                 if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3375                                                   ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3376                         status = false;
3377
3378                 glDeleteTextures(2, textures);
3379                 glUseProgram(0);
3380                 glDeleteProgram(program);
3381
3382                 return status;
3383         }
3384
3385         template <typename T>
3386         std::string GenFSMS(GLenum internalformat, const T& expected_value)
3387         {
3388                 std::ostringstream os;
3389                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3390                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3391                    << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3392                    << TypePrefix<T>()
3393                    << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3394                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3395                    << TypePrefix<T>() << "vec4" << expected_value
3396                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3397                    << TypePrefix<T>() << "vec4" << expected_value
3398                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3399                    << TypePrefix<T>() << "vec4" << expected_value
3400                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3401                    << TypePrefix<T>() << "vec4" << expected_value
3402                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3403                    << TypePrefix<T>() << "vec4" << expected_value
3404                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3405                    << TypePrefix<T>() << "vec4" << expected_value
3406                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3407                    << TypePrefix<T>() << "vec4" << expected_value
3408                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3409                    << TypePrefix<T>() << "vec4" << expected_value
3410                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3411                    << TypePrefix<T>() << "vec4" << expected_value
3412                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3413                    << TypePrefix<T>() << "vec4" << expected_value
3414                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3415                    << TypePrefix<T>() << "vec4" << expected_value
3416                    << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3417                    << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3418                 return os.str();
3419         }
3420 };
3421 //-----------------------------------------------------------------------------
3422 // 1.3.3 BasicAllTargetsAtomic
3423 //-----------------------------------------------------------------------------
3424 class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3425 {
3426         GLuint m_vao;
3427         GLuint m_vbo;
3428
3429         virtual long Setup()
3430         {
3431                 m_vao = 0;
3432                 m_vbo = 0;
3433                 return NO_ERROR;
3434         }
3435
3436         virtual long Run()
3437         {
3438                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3439
3440                 if (!Atomic<GLint>(GL_R32I))
3441                         return ERROR;
3442                 if (!Atomic<GLuint>(GL_R32UI))
3443                         return ERROR;
3444
3445                 if (!AtomicCube<GLint>(GL_R32I))
3446                         return ERROR;
3447                 if (!AtomicCube<GLuint>(GL_R32UI))
3448                         return ERROR;
3449
3450                 GLint isamples;
3451                 glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3452                 if (SupportedSamples(4) && isamples >= 4)
3453                 {
3454                         if (!AtomicMS<GLint>(GL_R32I))
3455                                 return ERROR;
3456                         if (!AtomicMS<GLuint>(GL_R32UI))
3457                                 return ERROR;
3458                 }
3459
3460                 return NO_ERROR;
3461         }
3462
3463         virtual long Cleanup()
3464         {
3465                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3466                 glDeleteVertexArrays(1, &m_vao);
3467                 glDeleteBuffers(1, &m_vbo);
3468                 return NO_ERROR;
3469         }
3470
3471         template <typename T>
3472         bool Atomic(GLenum internalformat)
3473         {
3474                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3475                                                          "  gl_Position = i_position;" NL "}";
3476                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3477                 GLuint           textures[7];
3478                 GLuint           buffer;
3479                 glGenTextures(7, textures);
3480                 glGenBuffers(1, &buffer);
3481
3482                 const int         kSize = 16;
3483                 std::vector<T> data(kSize * kSize * 2);
3484
3485                 glBindTexture(GL_TEXTURE_1D, textures[0]);
3486                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3487                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3488                 glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3489                 glBindTexture(GL_TEXTURE_1D, 0);
3490
3491                 glBindTexture(GL_TEXTURE_2D, textures[1]);
3492                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3493                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3494                 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3495                 glBindTexture(GL_TEXTURE_2D, 0);
3496
3497                 glBindTexture(GL_TEXTURE_3D, textures[2]);
3498                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3499                 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3500                 glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3501                 glBindTexture(GL_TEXTURE_3D, 0);
3502
3503                 glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3504                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3505                 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3506                 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3507                 glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3508
3509                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3510                 glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3511                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
3512                 glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3513                 glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3514                 glBindTexture(GL_TEXTURE_BUFFER, 0);
3515
3516                 glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3517                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3518                 glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3519                 glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3520                 glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3521
3522                 glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3523                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3524                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3525                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3526                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3527
3528                 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529                 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3530                 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3531                 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532                 glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3533                 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534                 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3535
3536                 glClear(GL_COLOR_BUFFER_BIT);
3537
3538                 glUseProgram(program);
3539                 glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3540                 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3541                 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3542                 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3543                 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3544                 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3545                 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3546
3547                 glBindVertexArray(m_vao);
3548                 glViewport(0, 0, kSize, 1);
3549                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3550
3551                 bool status = true;
3552
3553                 if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3554                 {
3555                         status = false;
3556                 }
3557
3558                 glUseProgram(0);
3559                 glDeleteProgram(program);
3560                 glDeleteTextures(7, textures);
3561                 glDeleteBuffers(1, &buffer);
3562
3563                 return status;
3564         }
3565
3566         template <typename T>
3567         bool AtomicCube(GLenum internalformat)
3568         {
3569                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3570                                                          "  gl_Position = i_position;" NL "}";
3571                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3572                 GLuint           textures[2];
3573                 glGenTextures(2, textures);
3574
3575                 const int         kSize = 16;
3576                 std::vector<T> data(kSize * kSize * 12);
3577
3578                 glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3579                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3580                 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3581                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3582                                          &data[0]);
3583                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3584                                          &data[0]);
3585                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3586                                          &data[0]);
3587                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3588                                          &data[0]);
3589                 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3590                                          &data[0]);
3591                 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3592                                          &data[0]);
3593                 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3594
3595                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3596                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3597                 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3598                 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3599                                          &data[0]);
3600                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3601
3602                 glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603                 glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3604
3605                 glClear(GL_COLOR_BUFFER_BIT);
3606
3607                 glUseProgram(program);
3608                 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3609                 glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3610
3611                 glBindVertexArray(m_vao);
3612                 glViewport(0, 0, kSize, kSize);
3613                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3614
3615                 bool status = true;
3616
3617                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3618                 {
3619                         status = false;
3620                 }
3621
3622                 glUseProgram(0);
3623                 glDeleteProgram(program);
3624                 glDeleteTextures(2, textures);
3625
3626                 return status;
3627         }
3628
3629         template <typename T>
3630         bool AtomicMS(GLenum internalformat)
3631         {
3632                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3633                                                          "  gl_Position = i_position;" NL "}";
3634                 const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3635                 GLuint           textures[2];
3636                 glGenTextures(2, textures);
3637
3638                 const int kSize = 16;
3639
3640                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3641                 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3642                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3643
3644                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3645                 glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3646                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3647
3648                 GLuint fbo;
3649                 glGenFramebuffers(1, &fbo);
3650                 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3651                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3652                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3653                 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3654                 const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3655                 glDrawBuffers(3, draw_buffers);
3656                 if (internalformat == GL_R32I)
3657                 {
3658                         const GLint value[4] = { 0, 0, 0, 0 };
3659                         glClearBufferiv(GL_COLOR, 0, value);
3660                         glClearBufferiv(GL_COLOR, 1, value);
3661                         glClearBufferiv(GL_COLOR, 2, value);
3662                 }
3663                 else
3664                 {
3665                         const GLuint value[4] = { 0, 0, 0, 0 };
3666                         glClearBufferuiv(GL_COLOR, 0, value);
3667                         glClearBufferuiv(GL_COLOR, 1, value);
3668                         glClearBufferuiv(GL_COLOR, 2, value);
3669                 }
3670                 glDeleteFramebuffers(1, &fbo);
3671
3672                 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3673                 glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3674
3675                 glUseProgram(program);
3676                 glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3677                 glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3678
3679                 glClear(GL_COLOR_BUFFER_BIT);
3680                 glBindVertexArray(m_vao);
3681                 glViewport(0, 0, kSize, kSize);
3682                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3683
3684                 bool status = true;
3685
3686                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3687                 {
3688                         status = false;
3689                 }
3690
3691                 glDeleteTextures(2, textures);
3692                 glUseProgram(0);
3693                 glDeleteProgram(program);
3694
3695                 return status;
3696         }
3697
3698         template <typename T>
3699         std::string GenFS(GLenum internalformat)
3700         {
3701                 std::ostringstream os;
3702                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3703                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3704                    << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3705                    << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3706                    << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3707                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3708                    << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3709                    << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3710                    << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3711                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3712                    << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3713                           "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3714
3715                         NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716                           "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717                           "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718                           "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719                           "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720                           "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721                           "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722                           "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723                           "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3724
3725                         NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726                           "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727                           "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728                           "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729                           "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730                           "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731                           "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732                           "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3733                           "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3734
3735                         NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736                           "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737                           "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738                           "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739                           "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740                           "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741                           "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3742                           "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3743                           "1.0);" NL
3744                           "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3745
3746                         NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747                           "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748                           "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749                           "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750                           "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751                           "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752                           "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753                           "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3754                           "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3755
3756                         NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757                           "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758                           "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759                           "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760                           "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761                           "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762                           "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763                           "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764                           "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3765
3766                         NL
3767                           "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768                           "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769                           "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770                           "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771                           "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772                           "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3773                           "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3774                           "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3775                           "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3776                           "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3777
3778                         NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779                           "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780                           "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781                           "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782                           "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783                           "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3784                           "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3785                           "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3786                           "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3787                           "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3788                 return os.str();
3789         }
3790
3791         template <typename T>
3792         std::string GenFSCube(GLenum internalformat)
3793         {
3794                 std::ostringstream os;
3795                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3796                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3797                    << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3798                    << TypePrefix<T>()
3799                    << "imageCube g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3800                           "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3801
3802                         NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803                           "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804                           "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805                           "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806                           "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807                           "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808                           "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3809                           "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3810                           "1.0);" NL
3811                           "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3812
3813                         NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3814                           "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3815                           "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3816                           "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3817                           "ivec3(coord, 0), 0) != 4) o_color = "
3818                           "vec4(1.0, 0.0, 0.0, 1.0);" NL
3819                           "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3820                           "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3821                           "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3822                           "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3823                           "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3824                           "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3825                           "1.0);" NL "}";
3826                 return os.str();
3827         }
3828
3829         template <typename T>
3830         std::string GenFSMS(GLenum internalformat)
3831         {
3832                 std::ostringstream os;
3833                 os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3834                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3835                    << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3836                    << TypePrefix<T>()
3837                    << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3838                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3839                           "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840                           "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841                           "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842                           "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843                           "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844                           "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845                           "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846                           "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3847                           "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3848                           "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3849                           "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3850                           "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3851                           "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3852                           "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3853                           "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3854                           "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3855                           "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3856                           "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3857                           "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3858                           "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3859                           "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3860                           "0.0, 1.0);" NL "}";
3861                 return os.str();
3862         }
3863 };
3864 //-----------------------------------------------------------------------------
3865 // LoadStoreMachine
3866 //-----------------------------------------------------------------------------
3867 class LoadStoreMachine : public ShaderImageLoadStoreBase
3868 {
3869         GLuint m_vao;
3870         int     m_stage;
3871
3872         virtual long Setup()
3873         {
3874                 glGenVertexArrays(1, &m_vao);
3875                 return NO_ERROR;
3876         }
3877
3878         virtual long Cleanup()
3879         {
3880                 glDisable(GL_RASTERIZER_DISCARD);
3881                 glDeleteVertexArrays(1, &m_vao);
3882                 return NO_ERROR;
3883         }
3884
3885         template <typename T>
3886         bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3887         {
3888                 const GLenum targets[] = { GL_TEXTURE_1D,               GL_TEXTURE_2D,
3889                                                                    GL_TEXTURE_3D,               GL_TEXTURE_RECTANGLE,
3890                                                                    GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3891                                                                    GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3892                 const int kTargets              = sizeof(targets) / sizeof(targets[0]);
3893                 GLuint  program_store = 0;
3894                 GLuint  program_load  = 0;
3895                 if (m_stage == 0)
3896                 { // VS
3897                         program_store =
3898                                 BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3899                         program_load =
3900                                 BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3901                 }
3902                 else if (m_stage == 1)
3903                 { // TCS
3904                         const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
3905                         const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3906                         program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3907                                                                                  glsl_tes, NULL, NULL);
3908                         program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3909                                                                                 glsl_tes, NULL, NULL);
3910                 }
3911                 else if (m_stage == 2)
3912                 { // TES
3913                         const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3914                         program_store =
3915                                 BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3916                         program_load =
3917                                 BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3918                 }
3919                 else if (m_stage == 3)
3920                 { // GS
3921                         const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3922                         program_store =
3923                                 BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3924                         program_load =
3925                                 BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3926                 }
3927                 else if (m_stage == 4)
3928                 { // CS
3929                         {
3930                                 std::string               source = GenStoreShader(m_stage, internalformat, write_value);
3931                                 const char* const src   = source.c_str();
3932                                 GLuint                    sh     = glCreateShader(GL_COMPUTE_SHADER);
3933                                 glShaderSource(sh, 1, &src, NULL);
3934                                 glCompileShader(sh);
3935                                 program_store = glCreateProgram();
3936                                 glAttachShader(program_store, sh);
3937                                 glLinkProgram(program_store);
3938                                 glDeleteShader(sh);
3939                         }
3940                         {
3941                                 std::string               source = GenLoadShader(m_stage, internalformat, expected_value);
3942                                 const char* const src   = source.c_str();
3943                                 GLuint                    sh     = glCreateShader(GL_COMPUTE_SHADER);
3944                                 glShaderSource(sh, 1, &src, NULL);
3945                                 glCompileShader(sh);
3946                                 program_load = glCreateProgram();
3947                                 glAttachShader(program_load, sh);
3948                                 glLinkProgram(program_load);
3949                                 glDeleteShader(sh);
3950                         }
3951                 }
3952                 GLuint textures[kTargets], texture_result;
3953                 glGenTextures(kTargets, textures);
3954                 glGenTextures(1, &texture_result);
3955
3956                 glBindTexture(GL_TEXTURE_2D, texture_result);
3957                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3958                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3959                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3960
3961                 for (int i = 0; i < kTargets; ++i)
3962                 {
3963                         glBindTexture(targets[i], textures[i]);
3964                         glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3965                         glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3966
3967                         if (targets[i] == GL_TEXTURE_1D)
3968                         {
3969                                 glTexStorage1D(targets[i], 1, internalformat, 1);
3970                         }
3971                         else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3972                         {
3973                                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3974                         }
3975                         else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3976                         {
3977                                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3978                         }
3979                         else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3980                         {
3981                                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3982                         }
3983                         else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3984                         {
3985                                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3986                         }
3987                         else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3988                         {
3989                                 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3990                         }
3991                 }
3992                 glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993                 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3994                 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3995                 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3996                 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997                 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998                 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999                 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
4000
4001                 glUseProgram(program_store);
4002                 glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4003                 glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4004                 glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4005                 glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4006                 glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4007                 glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4008                 glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4009                 glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4010
4011                 glBindVertexArray(m_vao);
4012                 if (m_stage == 1 || m_stage == 2)
4013                 { // TCS or TES
4014                         glPatchParameteri(GL_PATCH_VERTICES, 1);
4015                         glDrawArrays(GL_PATCHES, 0, 1);
4016                         glPatchParameteri(GL_PATCH_VERTICES, 3);
4017                 }
4018                 else if (m_stage == 4)
4019                 { // CS
4020                         glDispatchCompute(1, 1, 1);
4021                 }
4022                 else
4023                 {
4024                         glDrawArrays(GL_POINTS, 0, 1);
4025                 }
4026
4027                 bool status = true;
4028                 for (int i = 0; i < kTargets; ++i)
4029                 {
4030                         glBindTexture(targets[i], textures[i]);
4031                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4032
4033                         if (targets[i] == GL_TEXTURE_CUBE_MAP)
4034                         {
4035                                 for (int face = 0; face < 6; ++face)
4036                                 {
4037                                         T data;
4038                                         glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4039                                         if (!Equal(data, expected_value, internalformat))
4040                                         {
4041                                                 status = false;
4042                                                 m_context.getTestContext().getLog()
4043                                                         << tcu::TestLog::Message << "Value is: " << ToString(data)
4044                                                         << ". Value should be: " << ToString(expected_value)
4045                                                         << ". Format is: " << FormatEnumToString(internalformat)
4046                                                         << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4047                                                         << tcu::TestLog::EndMessage;
4048                                         }
4049                                 }
4050                         }
4051                         else
4052                         {
4053                                 T data[12];
4054                                 memset(&data[0], 0, sizeof(data));
4055                                 glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4056
4057                                 int count = 1;
4058                                 if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4059                                         count = 2;
4060                                 else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4061                                         count = 12;
4062                                 else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4063                                         count = 2;
4064
4065                                 for (int j = 0; j < count; ++j)
4066                                 {
4067                                         if (!Equal(data[j], expected_value, internalformat))
4068                                         {
4069                                                 status = false;
4070                                                 m_context.getTestContext().getLog()
4071                                                         << tcu::TestLog::Message << "Value is: " << ToString(data[j])
4072                                                         << ". Value should be: " << ToString(expected_value)
4073                                                         << ". Format is: " << FormatEnumToString(internalformat)
4074                                                         << ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4075                                                         << tcu::TestLog::EndMessage;
4076                                         }
4077                                 }
4078                         }
4079                 }
4080                 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4081                 glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4082                 glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4083                 glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4084                 glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4085                 glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4086                 glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4087                 glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088
4089                 glUseProgram(program_load);
4090                 glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4091                 glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4092                 glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4093                 glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4094                 glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4095                 glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4096                 glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4097                 glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4098
4099                 if (m_stage == 1 || m_stage == 2)
4100                 { // TCS or TES
4101                         glPatchParameteri(GL_PATCH_VERTICES, 1);
4102                         glDrawArrays(GL_PATCHES, 0, 1);
4103                         glPatchParameteri(GL_PATCH_VERTICES, 3);
4104                 }
4105                 else if (m_stage == 4)
4106                 { // CS
4107                         glDispatchCompute(1, 1, 1);
4108                 }
4109                 else
4110                 {
4111                         glDrawArrays(GL_POINTS, 0, 1);
4112                 }
4113                 {
4114                         vec4 color;
4115                         glBindTexture(GL_TEXTURE_2D, texture_result);
4116                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4117                         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4118                         if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4119                         {
4120                                 status = false;
4121                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4122                                                                                                         << ". Format is: " << FormatEnumToString(internalformat)
4123                                                                                                         << ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4124                         }
4125                 }
4126                 glUseProgram(0);
4127                 glDeleteProgram(program_store);
4128                 glDeleteProgram(program_load);
4129                 glDeleteTextures(kTargets, textures);
4130                 glDeleteTextures(1, &texture_result);
4131                 return status;
4132         }
4133
4134         template <typename T>
4135         std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4136         {
4137                 std::ostringstream os;
4138                 os << "#version 420 core";
4139                 if (stage == 4)
4140                 { // CS
4141                         os << NL "#extension GL_ARB_compute_shader : require";
4142                 }
4143                 os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4144                    << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4145                    << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4146                    << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4147                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4148                    << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4149                    << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4150                    << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4151                    << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4152                    << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4153                    << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4154                    << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4155                    << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4156                 if (stage == 0)
4157                 { // VS
4158                         os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4159                 }
4160                 else if (stage == 1)
4161                 { // TCS
4162                         os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4163                                          "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4164                                          "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4165                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4166                 }
4167                 else if (stage == 2)
4168                 { // TES
4169                         os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4170                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4171                 }
4172                 else if (stage == 3)
4173                 { // GS
4174                         os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4175                                          "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4176                 }
4177                 else if (stage == 4)
4178                 { // CS
4179                         os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4180                                          "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4181                 }
4182                 os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4183                                  "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4184                                  "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4185                                  "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4186                                  "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4187                                  "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4188                                  "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4189                                  "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4190                                  "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4191                                  "  for (int i = 0; i < 6; ++i) {" NL
4192                                  "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4193                                  "  for (int i = 0; i < 6; ++i) {" NL
4194                                  "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4195                 return os.str();
4196         }
4197
4198         template <typename T>
4199         std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4200         {
4201                 std::ostringstream os;
4202                 os << "#version 420 core";
4203                 if (stage == 4)
4204                 { // CS
4205                         os << NL "#extension GL_ARB_compute_shader : require";
4206                 }
4207                 os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4208                    << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4209                    << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4210                    << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4211                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4212                    << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4213                    << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4214                    << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4215                    << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4216                    << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4217                           "uniform "
4218                    << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4219                    << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4220                 if (stage == 0)
4221                 { // VS
4222                         os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4223                 }
4224                 else if (stage == 1)
4225                 { // TCS
4226                         os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4227                                          "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4228                                          "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4229                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4230                 }
4231                 else if (stage == 2)
4232                 { // TES
4233                         os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4234                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4235                 }
4236                 else if (stage == 3)
4237                 { // GS
4238                         os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4239                                          "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4240                 }
4241                 else if (stage == 4)
4242                 { // CS
4243                         os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4244                                          "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4245                 }
4246                 os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4247                    << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4248                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4249                           "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4250                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4251                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4252                           "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4253                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4254                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4255                           "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4256                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4257                           "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4258                           "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4259                 return os.str();
4260         }
4261
4262 protected:
4263         long RunStage(int stage)
4264         {
4265                 if (!SupportedInStage(stage, 8))
4266                         return NOT_SUPPORTED;
4267
4268                 glEnable(GL_RASTERIZER_DISCARD);
4269                 m_stage = stage;
4270
4271                 if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4272                         return ERROR;
4273                 if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4274                         return ERROR;
4275                 if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4276                         return ERROR;
4277
4278                 if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4279                         return ERROR;
4280                 if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4281                         return ERROR;
4282                 if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4283                         return ERROR;
4284
4285                 if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4286                         return ERROR;
4287                 if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4288                         return ERROR;
4289                 if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4290                         return ERROR;
4291
4292                 if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4293                         return ERROR;
4294
4295                 if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4296                         return ERROR;
4297                 if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4298                         return ERROR;
4299                 if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4300                         return ERROR;
4301
4302                 if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4303                         return ERROR;
4304                 if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4305                         return ERROR;
4306                 if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4307                         return ERROR;
4308
4309                 if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4310                         return ERROR;
4311                 if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4312                         return ERROR;
4313                 if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4314                         return ERROR;
4315                 if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4316                         return ERROR;
4317
4318                 if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4319                         return ERROR;
4320                 if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4321                         return ERROR;
4322                 if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4323                         return ERROR;
4324
4325                 if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4326                         return ERROR;
4327                 if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4328                         return ERROR;
4329                 if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4330                         return ERROR;
4331
4332                 if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4333                         return ERROR;
4334                 if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4335                         return ERROR;
4336                 if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4337                         return ERROR;
4338                 if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4339                         return ERROR;
4340
4341                 if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4342                         return ERROR;
4343                 if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4344                         return ERROR;
4345                 if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4346                         return ERROR;
4347
4348                 //
4349                 {
4350                         if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4351                                 return ERROR;
4352                         if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4353                                 return ERROR;
4354                         if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4355                                 return ERROR;
4356
4357                         if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4358                                 return ERROR;
4359                         if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4360                                 return ERROR;
4361                         if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4362                                 return ERROR;
4363                 }
4364                 return NO_ERROR;
4365         }
4366 };
4367 //-----------------------------------------------------------------------------
4368 // AtomicMachine
4369 //-----------------------------------------------------------------------------
4370 class AtomicMachine : public ShaderImageLoadStoreBase
4371 {
4372         GLuint m_vao;
4373
4374         virtual long Setup()
4375         {
4376                 glEnable(GL_RASTERIZER_DISCARD);
4377                 glGenVertexArrays(1, &m_vao);
4378                 return NO_ERROR;
4379         }
4380
4381         virtual long Cleanup()
4382         {
4383                 glDisable(GL_RASTERIZER_DISCARD);
4384                 glDeleteVertexArrays(1, &m_vao);
4385                 return NO_ERROR;
4386         }
4387
4388         template <typename T>
4389         bool Atomic(int stage, GLenum internalformat)
4390         {
4391                 GLuint program = 0;
4392                 if (stage == 0)
4393                 { // VS
4394                         program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4395                 }
4396                 else if (stage == 1)
4397                 { // TCS
4398                         const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
4399                         const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4400                         program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4401                 }
4402                 else if (stage == 2)
4403                 { // TES
4404                         const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4405                         program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4406                 }
4407                 else if (stage == 3)
4408                 { // GS
4409                         const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4410                         program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4411                 }
4412                 else if (stage == 4)
4413                 { // CS
4414                         std::string               source = GenShader<T>(stage, internalformat);
4415                         const char* const src   = source.c_str();
4416                         GLuint                    sh     = glCreateShader(GL_COMPUTE_SHADER);
4417                         glShaderSource(sh, 1, &src, NULL);
4418                         glCompileShader(sh);
4419                         program = glCreateProgram();
4420                         glAttachShader(program, sh);
4421                         glLinkProgram(program);
4422                         glDeleteShader(sh);
4423                 }
4424                 GLuint texture_result;
4425                 glGenTextures(1, &texture_result);
4426                 glBindTexture(GL_TEXTURE_2D, texture_result);
4427                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4428                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4429                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4430
4431                 const GLenum targets[] = { GL_TEXTURE_2D,        GL_TEXTURE_3D,    GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4432                                                                    GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4433                 const int kTargets = sizeof(targets) / sizeof(targets[0]);
4434
4435                 GLuint textures[kTargets];
4436                 GLuint buffer;
4437                 glGenTextures(kTargets, textures);
4438                 glGenBuffers(1, &buffer);
4439
4440                 for (int i = 0; i < kTargets; ++i)
4441                 {
4442                         glBindTexture(targets[i], textures[i]);
4443                         if (targets[i] != GL_TEXTURE_BUFFER)
4444                         {
4445                                 glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4446                                 glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4447                         }
4448                         if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4449                         {
4450                                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4451                         }
4452                         else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4453                         {
4454                                 glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4455                         }
4456                         else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4457                         {
4458                                 glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4459                         }
4460                         else if (targets[i] == GL_TEXTURE_BUFFER)
4461                         {
4462                                 glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4463                                 glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4464                                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
4465                                 glTexBuffer(targets[i], internalformat, buffer);
4466                         }
4467                         else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4468                         {
4469                                 glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4470                         }
4471                 }
4472                 glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4473                 glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4474                 glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4475                 glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4476                 glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4477                 glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4478                 glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4479                 glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4480
4481                 glUseProgram(program);
4482                 glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4483                 glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4484                 glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4485                 glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4486                 glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4487                 glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4488                 glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4489                 glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4490
4491                 glBindVertexArray(m_vao);
4492                 if (stage == 1 || stage == 2)
4493                 { // TCS or TES
4494                         glPatchParameteri(GL_PATCH_VERTICES, 1);
4495                         glDrawArrays(GL_PATCHES, 0, 1);
4496                         glPatchParameteri(GL_PATCH_VERTICES, 3);
4497                 }
4498                 else if (stage == 4)
4499                 { // CS
4500                         glDispatchCompute(1, 1, 1);
4501                 }
4502                 else
4503                 {
4504                         glDrawArrays(GL_POINTS, 0, 1);
4505                 }
4506
4507                 bool status = true;
4508                 {
4509                         vec4 color;
4510                         glBindTexture(GL_TEXTURE_2D, texture_result);
4511                         glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4512                         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4513                         if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4514                         {
4515                                 status = false;
4516                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4517                                                                                                         << ". Format is: " << FormatEnumToString(internalformat)
4518                                                                                                         << ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4519                         }
4520                 }
4521                 glUseProgram(0);
4522                 glDeleteProgram(program);
4523                 glDeleteTextures(7, textures);
4524                 glDeleteTextures(1, &texture_result);
4525                 glDeleteBuffers(1, &buffer);
4526                 return status;
4527         }
4528
4529         template <typename T>
4530         std::string GenShader(int stage, GLenum internalformat)
4531         {
4532                 std::ostringstream os;
4533                 os << "#version 420 core";
4534                 if (stage == 4)
4535                 { // CS
4536                         os << NL "#extension GL_ARB_compute_shader : require";
4537                 }
4538                 os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4539                    << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4540                    << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4541                    << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4542                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4543                    << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4544                    << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4545                    << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4546                    << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4547                    << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4548                           "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4549                 if (stage == 0)
4550                 { // VS
4551                         os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4552                 }
4553                 else if (stage == 1)
4554                 { // TCS
4555                         os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4556                                          "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4557                                          "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4558                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4559                 }
4560                 else if (stage == 2)
4561                 { // TES
4562                         os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4563                                          "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4564                 }
4565                 else if (stage == 3)
4566                 { // GS
4567                         os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4568                                          "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4569                 }
4570                 else if (stage == 4)
4571                 { // CS
4572                         os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4573                                          "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4574                 }
4575                 os << NL
4576                         "  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4577                         "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4578                         "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4579                         "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580                         "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581                         "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582                         "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583                         "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584                         "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585                         "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4586
4587                         NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4588                         "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4589                         "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4590                         "  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591                         "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592                         "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593                         "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594                         "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595                         "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596                         "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4597
4598                         NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4599                         "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4600                         "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4601                         "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602                         "  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603                         "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604                         "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605                         "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606                         "  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4607                         "1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4608
4609                         NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4610                         "ivec3(coord, 0), g_value[2]) != 0) "
4611                         "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612                         "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4613                         "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614                         "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615                         "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616                         "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617                         "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618                         "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4619                         "0.0, 1.0);" NL
4620                         "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4621
4622                         NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4623                         "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4624                         "  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4625                         "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626                         "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627                         "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628                         "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629                         "  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4630                         "1.0);" NL
4631                         "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4632                         "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4633
4634                         NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4635                         "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4636                         "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4637                         "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4638                         "1.0);" NL
4639                         "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4640                         "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4641                         "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4642                         "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4643                         "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4644                         "0.0, 0.0, 1.0);" NL
4645                         "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4646
4647                         NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4648                         "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4649                         "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4650                         "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4651                         "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652                         "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653                         "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4654                         "1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4655                         "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4656                         "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4657                         "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4658
4659                         NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4660                 return os.str();
4661         }
4662
4663 protected:
4664         long RunStage(int stage)
4665         {
4666                 if (!SupportedInStage(stage, 8))
4667                         return NOT_SUPPORTED;
4668                 if (!Atomic<GLint>(stage, GL_R32I))
4669                         return ERROR;
4670                 if (!Atomic<GLuint>(stage, GL_R32UI))
4671                         return ERROR;
4672                 return NO_ERROR;
4673         }
4674 };
4675 //-----------------------------------------------------------------------------
4676 // 1.3.4 BasicAllTargetsLoadStoreVS
4677 //-----------------------------------------------------------------------------
4678 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4679 {
4680         virtual long Run()
4681         {
4682                 return RunStage(0);
4683         }
4684 };
4685 //-----------------------------------------------------------------------------
4686 // 1.3.5 BasicAllTargetsLoadStoreTCS
4687 //-----------------------------------------------------------------------------
4688 class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4689 {
4690         virtual long Run()
4691         {
4692                 return RunStage(1);
4693         }
4694 };
4695 //-----------------------------------------------------------------------------
4696 // 1.3.6 BasicAllTargetsLoadStoreTES
4697 //-----------------------------------------------------------------------------
4698 class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4699 {
4700         virtual long Run()
4701         {
4702                 return RunStage(2);
4703         }
4704 };
4705 //-----------------------------------------------------------------------------
4706 // 1.3.7 BasicAllTargetsLoadStoreGS
4707 //-----------------------------------------------------------------------------
4708 class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4709 {
4710         virtual long Run()
4711         {
4712                 return RunStage(3);
4713         }
4714 };
4715 //-----------------------------------------------------------------------------
4716 // 1.3.8 BasicAllTargetsLoadStoreCS
4717 //-----------------------------------------------------------------------------
4718 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4719 {
4720         virtual long Run()
4721         {
4722                 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4723                 {
4724                         m_context.getTestContext().getLog()
4725                                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4726                                 << tcu::TestLog::EndMessage;
4727                         return NO_ERROR;
4728                 }
4729
4730                 return RunStage(4);
4731         }
4732 };
4733 //-----------------------------------------------------------------------------
4734 // 1.3.9 BasicAllTargetsAtomicVS
4735 //-----------------------------------------------------------------------------
4736 class BasicAllTargetsAtomicVS : public AtomicMachine
4737 {
4738         virtual long Run()
4739         {
4740                 return RunStage(0);
4741         }
4742 };
4743 //-----------------------------------------------------------------------------
4744 // 1.3.10 BasicAllTargetsAtomicTCS
4745 //-----------------------------------------------------------------------------
4746 class BasicAllTargetsAtomicTCS : public AtomicMachine
4747 {
4748         virtual long Run()
4749         {
4750                 return RunStage(1);
4751         }
4752 };
4753 //-----------------------------------------------------------------------------
4754 // 1.3.11 BasicAllTargetsAtomicTES
4755 //-----------------------------------------------------------------------------
4756 class BasicAllTargetsAtomicTES : public AtomicMachine
4757 {
4758         virtual long Run()
4759         {
4760                 return RunStage(2);
4761         }
4762 };
4763 //-----------------------------------------------------------------------------
4764 // 1.3.12 BasicAllTargetsAtomicGS
4765 //-----------------------------------------------------------------------------
4766 class BasicAllTargetsAtomicGS : public AtomicMachine
4767 {
4768         virtual long Run()
4769         {
4770                 return RunStage(3);
4771         }
4772 };
4773 //-----------------------------------------------------------------------------
4774 // 1.3.13 BasicAllTargetsAtomicCS
4775 //-----------------------------------------------------------------------------
4776 class BasicAllTargetsAtomicCS : public AtomicMachine
4777 {
4778         virtual long Run()
4779         {
4780                 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4781                 {
4782                         m_context.getTestContext().getLog()
4783                                 << tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4784                                 << tcu::TestLog::EndMessage;
4785                         return NO_ERROR;
4786                 }
4787
4788                 return RunStage(4);
4789         }
4790 };
4791 //-----------------------------------------------------------------------------
4792 // 1.4.1 BasicGLSLMisc
4793 //-----------------------------------------------------------------------------
4794 class BasicGLSLMisc : public ShaderImageLoadStoreBase
4795 {
4796         GLuint m_texture;
4797         GLuint m_program;
4798         GLuint m_vao, m_vbo;
4799
4800         virtual long Setup()
4801         {
4802                 m_texture = 0;
4803                 m_program = 0;
4804                 m_vao = m_vbo = 0;
4805                 return NO_ERROR;
4806         }
4807
4808         virtual long Run()
4809         {
4810                 const int                 kSize = 32;
4811                 std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4812
4813                 glGenTextures(1, &m_texture);
4814                 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4815                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4816                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4817                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4818
4819                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4820                                                          "  gl_Position = i_position;" NL "}";
4821                 const char* src_fs =
4822                         "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4823                         "layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4824                         "layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4825                         "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4826                         "  imageStore(g_image_layer0, coord, vec4(1.0));" NL "  memoryBarrier();" NL
4827                         "  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4828                         "  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4829                         "  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4830                 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4831
4832                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4833
4834                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4835                 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4836
4837                 glClear(GL_COLOR_BUFFER_BIT);
4838                 glViewport(0, 0, kSize, kSize);
4839
4840                 glUseProgram(m_program);
4841                 glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4842                 glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4843
4844                 glBindVertexArray(m_vao);
4845                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4846
4847                 if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4848                 {
4849                         return ERROR;
4850                 }
4851                 return NO_ERROR;
4852         }
4853
4854         virtual long Cleanup()
4855         {
4856                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4857                 glDeleteTextures(1, &m_texture);
4858                 glDeleteVertexArrays(1, &m_vao);
4859                 glDeleteBuffers(1, &m_vbo);
4860                 glUseProgram(0);
4861                 glDeleteProgram(m_program);
4862                 return NO_ERROR;
4863         }
4864 };
4865 //-----------------------------------------------------------------------------
4866 // 1.4.2 BasicGLSLEarlyFragTests
4867 //-----------------------------------------------------------------------------
4868 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4869 {
4870         GLuint m_texture[2];
4871         GLuint m_program[2];
4872         GLuint m_vao, m_vbo;
4873
4874         virtual long Setup()
4875         {
4876                 m_texture[0] = m_texture[1] = 0;
4877                 m_program[0] = m_program[1] = 0;
4878                 m_vao = m_vbo = 0;
4879                 return NO_ERROR;
4880         }
4881
4882         virtual long Run()
4883         {
4884                 int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4885
4886                 const int                 kSize = 32;
4887                 std::vector<vec4> data(kSize * kSize);
4888
4889                 glGenTextures(2, m_texture);
4890                 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4891                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4892                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4893                 glBindTexture(GL_TEXTURE_2D, 0);
4894
4895                 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4896                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4897                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4898                 glBindTexture(GL_TEXTURE_2D, 0);
4899
4900                 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4901                                                           "  gl_Position = i_position;" NL "}";
4902                 const char* glsl_early_frag_tests_fs =
4903                         "#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4904                         "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4905                         "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4906                         "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4907                 const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4908                                                           "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4909                                                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4910                                                           "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4911                 m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4912                 m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4913
4914                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4915
4916                 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4917                 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4918
4919                 glViewport(0, 0, kSize, kSize);
4920                 glBindVertexArray(m_vao);
4921
4922                 glEnable(GL_DEPTH_TEST);
4923                 glClearColor(0.0, 1.0f, 0.0, 1.0f);
4924                 glClearDepthf(0.0f);
4925
4926                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4927                 glUseProgram(m_program[0]);
4928                 glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4929
4930                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4931
4932                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4933                 glUseProgram(m_program[1]);
4934                 glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4935                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4936
4937                 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4938                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4939                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4940                 for (int i = 0; i < kSize * kSize; ++i)
4941                 {
4942                         if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4943                                 return ERROR;
4944                 }
4945
4946                 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4947                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4948                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4949                 for (int i = 0; i < kSize * kSize; ++i)
4950                 {
4951                         if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4952                                 return ERROR;
4953                 }
4954
4955                 return NO_ERROR;
4956         }
4957
4958         virtual long Cleanup()
4959         {
4960                 glDisable(GL_DEPTH_TEST);
4961                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4962                 glClearDepthf(1.0f);
4963                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
4964                 glDeleteTextures(2, m_texture);
4965                 glDeleteVertexArrays(1, &m_vao);
4966                 glDeleteBuffers(1, &m_vbo);
4967                 glUseProgram(0);
4968                 glDeleteProgram(m_program[0]);
4969                 glDeleteProgram(m_program[1]);
4970                 return NO_ERROR;
4971         }
4972 };
4973 //-----------------------------------------------------------------------------
4974 // 1.4.3 BasicGLSLConst
4975 //-----------------------------------------------------------------------------
4976 class BasicGLSLConst : public ShaderImageLoadStoreBase
4977 {
4978         GLuint m_program;
4979         GLuint m_vao, m_vbo;
4980
4981         virtual long Setup()
4982         {
4983                 m_program = 0;
4984                 m_vao = m_vbo = 0;
4985                 return NO_ERROR;
4986         }
4987
4988         virtual long Run()
4989         {
4990                 bool isAtLeast44Context =
4991                         glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4992
4993                 const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4994                                                          "  gl_Position = i_position;" NL "}";
4995                 std::ostringstream src_fs;
4996                 src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4997                 src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
4998                                          "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
4999                                          "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5000                                          "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5001                                          "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5002                                          "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5003                                          "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5004                 if (isAtLeast44Context)
5005                         src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5006                                                  "vec4(0.2, 0.0, 0.0, 0.2);";
5007                 else
5008                         src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5009                                                  "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5010                 src_fs << NL
5011                         "  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5012                         "  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5013                         "  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5014                         "0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5015                         "0.0, 0.0, 0.6);" NL
5016                         "  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5017                         "  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5018                         "  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5019
5020                 m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5021                 glUseProgram(m_program);
5022
5023                 GLint i;
5024                 glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5025                 glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5026
5027                 glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5028                 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5029
5030                 glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5031                 glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5032
5033                 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5034                 glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5035
5036                 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5037                 glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5038
5039                 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5040                 glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5041
5042                 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5043                 glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5044
5045                 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5046                 glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5047
5048                 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5049                 glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5050
5051                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5052
5053                 glClear(GL_COLOR_BUFFER_BIT);
5054                 glBindVertexArray(m_vao);
5055                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5056
5057                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5058                 {
5059                         return ERROR;
5060                 }
5061                 return NO_ERROR;
5062         }
5063
5064         virtual long Cleanup()
5065         {
5066                 glDeleteVertexArrays(1, &m_vao);
5067                 glDeleteBuffers(1, &m_vbo);
5068                 glUseProgram(0);
5069                 glDeleteProgram(m_program);
5070                 return NO_ERROR;
5071         }
5072 };
5073 //-----------------------------------------------------------------------------
5074 // 2.1.1 AdvancedSyncImageAccess
5075 //-----------------------------------------------------------------------------
5076 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5077 {
5078         GLuint m_buffer;
5079         GLuint m_buffer_tex;
5080         GLuint m_store_program;
5081         GLuint m_draw_program;
5082         GLuint m_attribless_vao;
5083
5084         virtual long Setup()
5085         {
5086                 m_buffer                 = 0;
5087                 m_buffer_tex     = 0;
5088                 m_store_program  = 0;
5089                 m_draw_program   = 0;
5090                 m_attribless_vao = 0;
5091                 return NO_ERROR;
5092         }
5093
5094         virtual long Run()
5095         {
5096                 if (!SupportedInVS(1))
5097                         return NOT_SUPPORTED;
5098                 const char* const glsl_store_vs =
5099                         "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5100                         "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5101                         "  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5102                 const char* const glsl_draw_vs =
5103                         "#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5104                         "uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5105                         "  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5106                         "  if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5107                         "  gl_Position = pi;" NL "}";
5108                 const char* const glsl_draw_fs =
5109                         "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5110                         "  o_color = vs_color;" NL "}";
5111                 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5112                 m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5113
5114                 glGenVertexArrays(1, &m_attribless_vao);
5115                 glBindVertexArray(m_attribless_vao);
5116
5117                 glGenBuffers(1, &m_buffer);
5118                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5119                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5120                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5121
5122                 glGenTextures(1, &m_buffer_tex);
5123                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5124                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5125
5126                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5127
5128                 glEnable(GL_RASTERIZER_DISCARD);
5129                 glUseProgram(m_store_program);
5130                 glDrawArrays(GL_POINTS, 0, 4);
5131
5132                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5133
5134                 glDisable(GL_RASTERIZER_DISCARD);
5135                 glClear(GL_COLOR_BUFFER_BIT);
5136                 glUseProgram(m_draw_program);
5137                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5138
5139                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5140                 {
5141                         return ERROR;
5142                 }
5143                 return NO_ERROR;
5144         }
5145
5146         virtual long Cleanup()
5147         {
5148                 glUseProgram(0);
5149                 glDeleteBuffers(1, &m_buffer);
5150                 glDeleteTextures(1, &m_buffer_tex);
5151                 glDeleteProgram(m_store_program);
5152                 glDeleteProgram(m_draw_program);
5153                 glDeleteVertexArrays(1, &m_attribless_vao);
5154                 return NO_ERROR;
5155         }
5156 };
5157 //-----------------------------------------------------------------------------
5158 // 2.1.2 AdvancedSyncVertexArray
5159 //-----------------------------------------------------------------------------
5160 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5161 {
5162         GLuint m_position_buffer;
5163         GLuint m_color_buffer;
5164         GLuint m_element_buffer;
5165         GLuint m_position_buffer_tex;
5166         GLuint m_color_buffer_tex;
5167         GLuint m_element_buffer_tex;
5168         GLuint m_store_program;
5169         GLuint m_draw_program;
5170         GLuint m_attribless_vao;
5171         GLuint m_draw_vao;
5172
5173         virtual long Setup()
5174         {
5175                 m_position_buffer        = 0;
5176                 m_color_buffer            = 0;
5177                 m_element_buffer          = 0;
5178                 m_position_buffer_tex = 0;
5179                 m_color_buffer_tex      = 0;
5180                 m_element_buffer_tex  = 0;
5181                 m_store_program           = 0;
5182                 m_draw_program            = 0;
5183                 m_attribless_vao          = 0;
5184                 m_draw_vao                        = 0;
5185                 return NO_ERROR;
5186         }
5187
5188         virtual long Run()
5189         {
5190                 if (!SupportedInVS(3))
5191                         return NOT_SUPPORTED;
5192                 const char* const glsl_store_vs =
5193                         "#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5194                         "layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5195                         "layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5196                         "void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5197                         "  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5198                         "  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5199                         "  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5200                 const char* const glsl_draw_vs =
5201                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5202                         "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5203                         "  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5204                 const char* const glsl_draw_fs =
5205                         "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5206                         "  o_color = vs_color;" NL "}";
5207                 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5208                 glUseProgram(m_store_program);
5209                 glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5210                 glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5211                 glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5212                 glUseProgram(0);
5213
5214                 m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5215
5216                 glGenBuffers(1, &m_position_buffer);
5217                 glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5218                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5219                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5220
5221                 glGenBuffers(1, &m_color_buffer);
5222                 glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5223                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5224                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5225
5226                 glGenBuffers(1, &m_element_buffer);
5227                 glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5228                 glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5229                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5230
5231                 glGenTextures(1, &m_position_buffer_tex);
5232                 glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5233                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5234                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5235
5236                 glGenTextures(1, &m_color_buffer_tex);
5237                 glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5238                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5239                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5240
5241                 glGenTextures(1, &m_element_buffer_tex);
5242                 glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5243                 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5244                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5245
5246                 glGenVertexArrays(1, &m_attribless_vao);
5247
5248                 glGenVertexArrays(1, &m_draw_vao);
5249                 glBindVertexArray(m_draw_vao);
5250                 glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5251                 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5252                 glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5253                 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5254                 glBindBuffer(GL_ARRAY_BUFFER, 0);
5255                 glEnableVertexAttribArray(0);
5256                 glEnableVertexAttribArray(1);
5257                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5258                 glBindVertexArray(0);
5259
5260                 glEnable(GL_RASTERIZER_DISCARD);
5261                 glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5262                 glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5263                 glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5264                 glUseProgram(m_store_program);
5265                 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5266                 glBindVertexArray(m_attribless_vao);
5267                 glDrawArrays(GL_POINTS, 0, 4);
5268
5269                 glDisable(GL_RASTERIZER_DISCARD);
5270                 glClear(GL_COLOR_BUFFER_BIT);
5271                 glUseProgram(m_draw_program);
5272                 glBindVertexArray(m_draw_vao);
5273                 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5274                 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5275
5276                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5277                 {
5278                         return ERROR;
5279                 }
5280
5281                 glEnable(GL_RASTERIZER_DISCARD);
5282                 glUseProgram(m_store_program);
5283                 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5284                 glBindVertexArray(m_attribless_vao);
5285                 glDrawArrays(GL_POINTS, 0, 4);
5286
5287                 glDisable(GL_RASTERIZER_DISCARD);
5288                 glClear(GL_COLOR_BUFFER_BIT);
5289                 glUseProgram(m_draw_program);
5290                 glBindVertexArray(m_draw_vao);
5291                 glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5292                 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5293
5294                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5295                 {
5296                         return ERROR;
5297                 }
5298                 return NO_ERROR;
5299         }
5300
5301         virtual long Cleanup()
5302         {
5303                 glDisable(GL_RASTERIZER_DISCARD);
5304                 glUseProgram(0);
5305                 glDeleteBuffers(1, &m_position_buffer);
5306                 glDeleteBuffers(1, &m_color_buffer);
5307                 glDeleteBuffers(1, &m_element_buffer);
5308                 glDeleteTextures(1, &m_position_buffer_tex);
5309                 glDeleteTextures(1, &m_color_buffer_tex);
5310                 glDeleteTextures(1, &m_element_buffer_tex);
5311                 glDeleteProgram(m_store_program);
5312                 glDeleteProgram(m_draw_program);
5313                 glDeleteVertexArrays(1, &m_attribless_vao);
5314                 glDeleteVertexArrays(1, &m_draw_vao);
5315                 return NO_ERROR;
5316         }
5317 };
5318
5319 //-----------------------------------------------------------------------------
5320 // 2.1.4 AdvancedSyncDrawIndirect
5321 //-----------------------------------------------------------------------------
5322 class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5323 {
5324         GLuint m_draw_command_buffer;
5325         GLuint m_draw_command_buffer_tex;
5326         GLuint m_store_program;
5327         GLuint m_draw_program;
5328         GLuint m_attribless_vao;
5329         GLuint m_draw_vao;
5330         GLuint m_draw_vbo;
5331
5332         virtual long Setup()
5333         {
5334                 m_draw_command_buffer    = 0;
5335                 m_draw_command_buffer_tex = 0;
5336                 m_store_program                   = 0;
5337                 m_draw_program                    = 0;
5338                 m_attribless_vao                  = 0;
5339                 m_draw_vao                                = 0;
5340                 m_draw_vbo                                = 0;
5341                 return NO_ERROR;
5342         }
5343
5344         virtual long Run()
5345         {
5346                 if (!SupportedInVS(1))
5347                         return NOT_SUPPORTED;
5348                 const char* const glsl_store_vs =
5349                         "#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5350                         "  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5351                 const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5352                                                                                  "void main() {" NL "  gl_Position = i_position;" NL "}";
5353                 const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5354                                                                                  "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5355                 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5356                 m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5357
5358                 glGenBuffers(1, &m_draw_command_buffer);
5359                 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5360                 glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5361                 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5362
5363                 glGenTextures(1, &m_draw_command_buffer_tex);
5364                 glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5365                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5366                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5367
5368                 glGenVertexArrays(1, &m_attribless_vao);
5369                 CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5370
5371                 glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5372
5373                 glEnable(GL_RASTERIZER_DISCARD);
5374                 glUseProgram(m_store_program);
5375                 glBindVertexArray(m_attribless_vao);
5376                 glDrawArrays(GL_POINTS, 0, 1);
5377
5378                 glDisable(GL_RASTERIZER_DISCARD);
5379                 glClear(GL_COLOR_BUFFER_BIT);
5380                 glUseProgram(m_draw_program);
5381                 glBindVertexArray(m_draw_vao);
5382                 glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5383                 glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5384                 glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5385
5386                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5387                 {
5388                         return ERROR;
5389                 }
5390                 return NO_ERROR;
5391         }
5392
5393         virtual long Cleanup()
5394         {
5395                 glUseProgram(0);
5396                 glDeleteBuffers(1, &m_draw_command_buffer);
5397                 glDeleteTextures(1, &m_draw_command_buffer_tex);
5398                 glDeleteProgram(m_store_program);
5399                 glDeleteProgram(m_draw_program);
5400                 glDeleteVertexArrays(1, &m_attribless_vao);
5401                 glDeleteVertexArrays(1, &m_draw_vao);
5402                 glDeleteBuffers(1, &m_draw_vbo);
5403                 return NO_ERROR;
5404         }
5405 };
5406 //-----------------------------------------------------------------------------
5407 // 2.1.5 AdvancedSyncTextureUpdate
5408 //-----------------------------------------------------------------------------
5409 class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5410 {
5411         GLuint m_texture;
5412         GLuint m_store_program;
5413         GLuint m_draw_program;
5414         GLuint m_vao;
5415         GLuint m_vbo;
5416         GLuint m_pbo;
5417
5418         virtual long Setup()
5419         {
5420                 m_texture               = 0;
5421                 m_store_program = 0;
5422                 m_draw_program  = 0;
5423                 m_vao                   = 0;
5424                 m_vbo                   = 0;
5425                 m_pbo                   = 0;
5426                 return NO_ERROR;
5427         }
5428
5429         virtual long Run()
5430         {
5431                 const char* const glsl_vs =
5432                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5433                         "void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5434                 const char* const glsl_store_fs =
5435                         "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5436                         "  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5437                 const char* const glsl_draw_fs =
5438                         "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5439                         "uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5440                 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5441                 m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5442
5443                 std::vector<vec4> data(16 * 16, vec4(1.0f));
5444                 glGenBuffers(1, &m_pbo);
5445                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5446                 glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5447                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5448
5449                 glGenTextures(1, &m_texture);
5450                 glBindTexture(GL_TEXTURE_2D, m_texture);
5451                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5452                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5453                 glBindTexture(GL_TEXTURE_2D, 0);
5454
5455                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5456
5457                 glViewport(0, 0, 16, 16);
5458                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5459                 glUseProgram(m_store_program);
5460                 glBindVertexArray(m_vao);
5461                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5462
5463                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5464                 glBindTexture(GL_TEXTURE_2D, m_texture);
5465                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5466                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5467                 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5468
5469                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5470                 glClear(GL_COLOR_BUFFER_BIT);
5471                 glUseProgram(m_draw_program);
5472                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5473
5474                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5475                 {
5476                         return ERROR;
5477                 }
5478                 return NO_ERROR;
5479         }
5480
5481         virtual long Cleanup()
5482         {
5483                 glUseProgram(0);
5484                 glDeleteBuffers(1, &m_vbo);
5485                 glDeleteBuffers(1, &m_pbo);
5486                 glDeleteTextures(1, &m_texture);
5487                 glDeleteProgram(m_store_program);
5488                 glDeleteProgram(m_draw_program);
5489                 glDeleteVertexArrays(1, &m_vao);
5490                 return NO_ERROR;
5491         }
5492 };
5493 //-----------------------------------------------------------------------------
5494 // 2.1.6 AdvancedSyncImageAccess2
5495 //-----------------------------------------------------------------------------
5496 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5497 {
5498         GLuint m_texture;
5499         GLuint m_store_program;
5500         GLuint m_draw_program;
5501         GLuint m_vao;
5502         GLuint m_vbo;
5503
5504         virtual long Setup()
5505         {
5506                 m_texture               = 0;
5507                 m_store_program = 0;
5508                 m_draw_program  = 0;
5509                 m_vao                   = 0;
5510                 m_vbo                   = 0;
5511                 return NO_ERROR;
5512         }
5513
5514         virtual long Run()
5515         {
5516                 const char* const glsl_vs =
5517                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5518                         "void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5519                 const char* const glsl_store_fs =
5520                         "#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5521                         "  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5522                 const char* const glsl_draw_fs =
5523                         "#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5524                         "uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5525                 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5526                 m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5527
5528                 int width  = getWindowWidth();
5529                 int height = getWindowHeight();
5530                 scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5531
5532                 glGenTextures(1, &m_texture);
5533                 glBindTexture(GL_TEXTURE_2D, m_texture);
5534                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5535                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5536                 glBindTexture(GL_TEXTURE_2D, 0);
5537
5538                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5539
5540                 glViewport(0, 0, width, height);
5541                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5542                 glUseProgram(m_store_program);
5543                 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5544                 glBindVertexArray(m_vao);
5545                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5546
5547                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5548
5549                 glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5550                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5551
5552                 glClear(GL_COLOR_BUFFER_BIT);
5553                 glBindTexture(GL_TEXTURE_2D, m_texture);
5554                 glUseProgram(m_draw_program);
5555                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5556
5557                 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5558                 {
5559                         return ERROR;
5560                 }
5561                 return NO_ERROR;
5562         }
5563
5564         virtual long Cleanup()
5565         {
5566                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5567                 glUseProgram(0);
5568                 glDeleteBuffers(1, &m_vbo);
5569                 glDeleteTextures(1, &m_texture);
5570                 glDeleteProgram(m_store_program);
5571                 glDeleteProgram(m_draw_program);
5572                 glDeleteVertexArrays(1, &m_vao);
5573                 return NO_ERROR;
5574         }
5575 };
5576 //-----------------------------------------------------------------------------
5577 // 2.1.7 AdvancedSyncBufferUpdate
5578 //-----------------------------------------------------------------------------
5579 class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5580 {
5581         GLuint m_buffer;
5582         GLuint m_buffer_tex;
5583         GLuint m_store_program;
5584         GLuint m_attribless_vao;
5585
5586         virtual long Setup()
5587         {
5588                 m_buffer                 = 0;
5589                 m_buffer_tex     = 0;
5590                 m_store_program  = 0;
5591                 m_attribless_vao = 0;
5592                 return NO_ERROR;
5593         }
5594
5595         virtual long Run()
5596         {
5597                 if (!SupportedInVS(1))
5598                         return NOT_SUPPORTED;
5599                 const char* const glsl_store_vs =
5600                         "#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5601                         "  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5602                 m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5603
5604                 glGenVertexArrays(1, &m_attribless_vao);
5605                 glBindVertexArray(m_attribless_vao);
5606
5607                 glGenBuffers(1, &m_buffer);
5608                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5609                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5610                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5611
5612                 glGenTextures(1, &m_buffer_tex);
5613                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5614                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5615
5616                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5617
5618                 glEnable(GL_RASTERIZER_DISCARD);
5619                 glUseProgram(m_store_program);
5620                 glDrawArrays(GL_POINTS, 0, 1000);
5621
5622                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5623
5624                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5625                 vec4* ptr =
5626                         reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5627                 for (int i = 0; i < 1000; ++i)
5628                 {
5629                         if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5630                         {
5631                                 m_context.getTestContext().getLog()
5632                                         << tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5633                                 return ERROR;
5634                         }
5635                 }
5636                 return NO_ERROR;
5637         }
5638
5639         virtual long Cleanup()
5640         {
5641                 glDisable(GL_RASTERIZER_DISCARD);
5642                 glUseProgram(0);
5643                 glDeleteBuffers(1, &m_buffer);
5644                 glDeleteTextures(1, &m_buffer_tex);
5645                 glDeleteProgram(m_store_program);
5646                 glDeleteVertexArrays(1, &m_attribless_vao);
5647                 return NO_ERROR;
5648         }
5649 };
5650 //-----------------------------------------------------------------------------
5651 // 2.2.1 AdvancedAllStagesOneImage
5652 //-----------------------------------------------------------------------------
5653 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5654 {
5655         GLuint m_program;
5656         GLuint m_vao;
5657         GLuint m_vbo;
5658         GLuint m_ebo;
5659         GLuint m_buffer;
5660         GLuint m_buffer_tex;
5661         GLuint m_texture;
5662
5663         virtual long Setup()
5664         {
5665                 m_program       = 0;
5666                 m_vao            = 0;
5667                 m_vbo            = 0;
5668                 m_ebo            = 0;
5669                 m_buffer         = 0;
5670                 m_buffer_tex = 0;
5671                 m_texture       = 0;
5672                 return NO_ERROR;
5673         }
5674
5675         virtual long Run()
5676         {
5677                 if (!SupportedInGeomStages(2))
5678                         return NOT_SUPPORTED;
5679                 const char* const glsl_vs =
5680                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5681                         "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5682                         "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5683                         "  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5684                         "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5685                 const char* const glsl_tcs =
5686                         "#version 420 core" NL "layout(vertices = 1) out;" NL
5687                         "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5688                         "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5689                         "  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5690                         "  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5691                         "  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5692                         "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5693                 const char* const glsl_tes =
5694                         "#version 420 core" NL "layout(triangles, point_mode) in;" NL
5695                         "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5696                         "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5697                         "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5698                         "  gl_Position = gl_in[0].gl_Position;" NL "}";
5699                 const char* const glsl_gs =
5700                         "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5701                         "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5702                         "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5703                         "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5704                         "  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5705                 const char* const glsl_fs =
5706                         "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5707                         "layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5708                         "layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5709                         "  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5710                         "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5711                 m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5712                 glUseProgram(m_program);
5713                 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5714                 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5715
5716                 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5717
5718                 GLint i32 = 0;
5719                 glGenBuffers(1, &m_buffer);
5720                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5721                 glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5722                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5723
5724                 glGenTextures(1, &m_buffer_tex);
5725                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5726                 glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5727                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5728
5729                 GLuint ui32 = 0;
5730                 glGenTextures(1, &m_texture);
5731                 glBindTexture(GL_TEXTURE_2D, m_texture);
5732                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5733                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5734                 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5735                 glBindTexture(GL_TEXTURE_2D, 0);
5736
5737                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5738                 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5739
5740                 glBindVertexArray(m_vao);
5741                 glPatchParameteri(GL_PATCH_VERTICES, 1);
5742
5743                 glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5744                 glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5745
5746                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5747                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5748                 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5749                 if (i32 < 20 || i32 > 50)
5750                 {
5751                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5752                                                                                                 << " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5753                         return ERROR;
5754                 }
5755
5756                 glBindTexture(GL_TEXTURE_2D, m_texture);
5757                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5758                 if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5759                 {
5760                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5761                                                                                                 << (2 * i32) << tcu::TestLog::EndMessage;
5762                         return ERROR;
5763                 }
5764
5765                 return NO_ERROR;
5766         }
5767
5768         virtual long Cleanup()
5769         {
5770                 glPatchParameteri(GL_PATCH_VERTICES, 3);
5771                 glUseProgram(0);
5772                 glDeleteBuffers(1, &m_buffer);
5773                 glDeleteBuffers(1, &m_vbo);
5774                 glDeleteBuffers(1, &m_ebo);
5775                 glDeleteTextures(1, &m_buffer_tex);
5776                 glDeleteTextures(1, &m_texture);
5777                 glDeleteProgram(m_program);
5778                 glDeleteVertexArrays(1, &m_vao);
5779                 return NO_ERROR;
5780         }
5781 };
5782 //-----------------------------------------------------------------------------
5783 // 2.3.1 AdvancedMemoryDependentInvocation
5784 //-----------------------------------------------------------------------------
5785 class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5786 {
5787         GLuint m_buffer;
5788         GLuint m_buffer_tex;
5789         GLuint m_texture;
5790         GLuint m_program;
5791         GLuint m_vao;
5792         GLuint m_vbo;
5793
5794         virtual long Setup()
5795         {
5796                 m_buffer         = 0;
5797                 m_buffer_tex = 0;
5798                 m_texture       = 0;
5799                 m_program       = 0;
5800                 m_vao            = 0;
5801                 m_vbo            = 0;
5802                 return NO_ERROR;
5803         }
5804
5805         virtual long Run()
5806         {
5807                 if (!SupportedInVS(2))
5808                         return NOT_SUPPORTED;
5809                 const char* const glsl_vs =
5810                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5811                         "layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5812                         "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5813                         "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5814                         "  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5815                         "  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5816                 const char* const glsl_fs =
5817                         "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5818                         "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5819                         "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5820                         "  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5821                         "  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5822                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5823                 glUseProgram(m_program);
5824                 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5825                 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5826
5827                 vec4 zero(0);
5828                 glGenBuffers(1, &m_buffer);
5829                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5830                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5831                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5832
5833                 glGenTextures(1, &m_buffer_tex);
5834                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5835                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5836                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5837
5838                 glGenTextures(1, &m_texture);
5839                 glBindTexture(GL_TEXTURE_2D, m_texture);
5840                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5841                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5842                 glBindTexture(GL_TEXTURE_2D, 0);
5843
5844                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5845                 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5846
5847                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5848
5849                 glClear(GL_COLOR_BUFFER_BIT);
5850                 glBindVertexArray(m_vao);
5851                 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5852
5853                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5854                 {
5855                         return ERROR;
5856                 }
5857                 return NO_ERROR;
5858         }
5859
5860         virtual long Cleanup()
5861         {
5862                 glUseProgram(0);
5863                 glDeleteBuffers(1, &m_vbo);
5864                 glDeleteBuffers(1, &m_buffer);
5865                 glDeleteTextures(1, &m_texture);
5866                 glDeleteTextures(1, &m_buffer_tex);
5867                 glDeleteProgram(m_program);
5868                 glDeleteVertexArrays(1, &m_vao);
5869                 return NO_ERROR;
5870         }
5871 };
5872 //-----------------------------------------------------------------------------
5873 // 2.3.2 AdvancedMemoryOrder
5874 //-----------------------------------------------------------------------------
5875 class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5876 {
5877         GLuint m_buffer;
5878         GLuint m_buffer_tex;
5879         GLuint m_texture;
5880         GLuint m_program;
5881         GLuint m_vao;
5882         GLuint m_vbo;
5883
5884         virtual long Setup()
5885         {
5886                 m_buffer         = 0;
5887                 m_buffer_tex = 0;
5888                 m_texture       = 0;
5889                 m_program       = 0;
5890                 m_vao            = 0;
5891                 m_vbo            = 0;
5892                 return NO_ERROR;
5893         }
5894
5895         virtual long Run()
5896         {
5897                 if (!SupportedInVS(1))
5898                         return NOT_SUPPORTED;
5899                 const char* const glsl_vs =
5900                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5901                         "layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5902                         "  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5903                         "  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5904                         "  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5905                         "  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5906                 const char* const glsl_fs =
5907                         "#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5908                         "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5909                         "  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5910                         "    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5911                         "    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5912                         "}";
5913                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5914                 glUseProgram(m_program);
5915                 glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5916                 glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5917
5918                 glGenBuffers(1, &m_buffer);
5919                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5920                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5921                 glBindBuffer(GL_TEXTURE_BUFFER, 0);
5922
5923                 glGenTextures(1, &m_buffer_tex);
5924                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5925                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5926                 glBindTexture(GL_TEXTURE_BUFFER, 0);
5927
5928                 int width  = getWindowWidth();
5929                 int height = getWindowHeight();
5930                 scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5931
5932                 std::vector<vec4> data(width * height);
5933                 glGenTextures(1, &m_texture);
5934                 glBindTexture(GL_TEXTURE_2D, m_texture);
5935                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5936                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5937                 glBindTexture(GL_TEXTURE_2D, 0);
5938
5939                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5940                 glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5941
5942                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5943
5944                 glClear(GL_COLOR_BUFFER_BIT);
5945                 glViewport(0, 0, width, height);
5946                 glBindVertexArray(m_vao);
5947                 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5948
5949                 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5950                 {
5951                         return ERROR;
5952                 }
5953                 return NO_ERROR;
5954         }
5955
5956         virtual long Cleanup()
5957         {
5958                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
5959                 glUseProgram(0);
5960                 glDeleteBuffers(1, &m_vbo);
5961                 glDeleteBuffers(1, &m_buffer);
5962                 glDeleteTextures(1, &m_texture);
5963                 glDeleteTextures(1, &m_buffer_tex);
5964                 glDeleteProgram(m_program);
5965                 glDeleteVertexArrays(1, &m_vao);
5966                 return NO_ERROR;
5967         }
5968 };
5969 //-----------------------------------------------------------------------------
5970 // 2.4.1 AdvancedSSOSimple
5971 //-----------------------------------------------------------------------------
5972 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5973 {
5974         GLuint m_texture;
5975         GLuint m_pipeline[2];
5976         GLuint m_vsp, m_fsp0, m_fsp1;
5977         GLuint m_vao, m_vbo;
5978
5979         virtual long Setup()
5980         {
5981                 glGenTextures(1, &m_texture);
5982                 glGenProgramPipelines(2, m_pipeline);
5983                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5984
5985                 const char* const glsl_vs =
5986                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5987                         "  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5988                 const char* const glsl_fs0 =
5989                         "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5990                         "  for (int i = 0; i < g_image.length(); ++i) {" NL
5991                         "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
5992                 const char* const glsl_fs1 =
5993                         "#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5994                         "  for (int i = 0; i < g_image.length(); ++i) {" NL
5995                         "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
5996                 m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5997                 m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
5998                 m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
5999
6000                 return NO_ERROR;
6001         }
6002
6003         virtual long Run()
6004         {
6005                 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6006                 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6007                 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6008                 glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6009
6010                 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6011                 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6012                 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6013                 glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6014
6015                 glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6016                 glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6017
6018                 glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6019                 glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6020
6021                 int width  = getWindowWidth();
6022                 int height = getWindowHeight();
6023                 scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6024
6025                 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6026                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6027                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6028
6029                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6030                 glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6031                 glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6032                 glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6033                 glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6034                 glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6035                 glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6036                 glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6037
6038                 glBindVertexArray(m_vao);
6039
6040                 glViewport(0, 0, width, height);
6041                 glBindProgramPipeline(m_pipeline[0]);
6042                 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6043
6044                 glBindProgramPipeline(m_pipeline[1]);
6045                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6046
6047                 std::vector<vec4> data(width * height * 8);
6048                 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6049
6050                 for (int layer = 0; layer < 8; ++layer)
6051                 {
6052                         for (int h = 0; h < height; ++h)
6053                         {
6054                                 for (int w = 0; w < width; ++w)
6055                                 {
6056                                         const vec4 c = data[layer * width * height + h * width + w];
6057                                         if (layer % 2)
6058                                         {
6059                                                 if (!IsEqual(c, vec4(2.0f)))
6060                                                 {
6061                                                         return ERROR;
6062                                                 }
6063                                         }
6064                                         else
6065                                         {
6066                                                 if (!IsEqual(c, vec4(1.0f)))
6067                                                 {
6068                                                         return ERROR;
6069                                                 }
6070                                         }
6071                                 }
6072                         }
6073                 }
6074                 return NO_ERROR;
6075         }
6076
6077         virtual long Cleanup()
6078         {
6079                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6080                 glDeleteBuffers(1, &m_vbo);
6081                 glDeleteTextures(1, &m_texture);
6082                 glDeleteProgram(m_vsp);
6083                 glDeleteProgram(m_fsp0);
6084                 glDeleteProgram(m_fsp1);
6085                 glDeleteVertexArrays(1, &m_vao);
6086                 glDeleteProgramPipelines(2, m_pipeline);
6087                 return NO_ERROR;
6088         }
6089 };
6090 //-----------------------------------------------------------------------------
6091 // 2.4.2 AdvancedSSOAtomicCounters
6092 //-----------------------------------------------------------------------------
6093 class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6094 {
6095         GLuint m_buffer, m_buffer_tex;
6096         GLuint m_counter_buffer;
6097         GLuint m_transform_buffer;
6098         GLuint m_pipeline;
6099         GLuint m_vao, m_vbo;
6100         GLuint m_vsp, m_fsp;
6101
6102         virtual long Setup()
6103         {
6104                 m_vao = 0;
6105                 m_vbo = 0;
6106                 m_vsp = 0;
6107                 m_fsp = 0;
6108                 glGenBuffers(1, &m_buffer);
6109                 glGenTextures(1, &m_buffer_tex);
6110                 glGenBuffers(1, &m_counter_buffer);
6111                 glGenBuffers(1, &m_transform_buffer);
6112                 glGenProgramPipelines(1, &m_pipeline);
6113                 return NO_ERROR;
6114         }
6115
6116         virtual long Run()
6117         {
6118                 if (!SupportedInVS(1))
6119                         return NOT_SUPPORTED;
6120
6121                 CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6122                 const char* const glsl_vs =
6123                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6124                         "layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6125                         "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6126                         "  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6127                         "layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6128                         "  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6129                         "  const uint index = atomicCounterIncrement(g_counter);" NL
6130                         "  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6131                 const char* const glsl_fs =
6132                         "#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6133                         "layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6134                 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6135                 m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6136
6137                 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6138                 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6139
6140                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6141                 glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6142
6143                 glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6144                 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6145
6146                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6147                 vec4 zero(0);
6148                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6149
6150                 glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6151                 mat4 identity(1);
6152                 glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6153
6154                 glClear(GL_COLOR_BUFFER_BIT);
6155                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6156                 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6157                 glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6158                 glBindVertexArray(m_vao);
6159                 glBindProgramPipeline(m_pipeline);
6160                 glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6161
6162                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6163                 {
6164                         return ERROR;
6165                 }
6166
6167                 std::vector<vec4> data(4);
6168                 glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6169                 glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6170
6171                 for (int i = 0; i < 4; ++i)
6172                 {
6173                         if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6174                                 !IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6175                         {
6176                                 return ERROR;
6177                         }
6178                 }
6179
6180                 return NO_ERROR;
6181         }
6182
6183         virtual long Cleanup()
6184         {
6185                 glDeleteBuffers(1, &m_buffer);
6186                 glDeleteBuffers(1, &m_vbo);
6187                 glDeleteBuffers(1, &m_counter_buffer);
6188                 glDeleteBuffers(1, &m_transform_buffer);
6189                 glDeleteTextures(1, &m_buffer_tex);
6190                 glDeleteProgram(m_vsp);
6191                 glDeleteProgram(m_fsp);
6192                 glDeleteVertexArrays(1, &m_vao);
6193                 glDeleteProgramPipelines(1, &m_pipeline);
6194                 return NO_ERROR;
6195         }
6196 };
6197 //-----------------------------------------------------------------------------
6198 // 2.4.3 AdvancedSSOSubroutine
6199 //-----------------------------------------------------------------------------
6200 class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6201 {
6202         GLuint m_texture;
6203         GLuint m_attribless_vao;
6204         GLuint m_program;
6205         GLint  m_draw_buffer;
6206
6207         virtual long Setup()
6208         {
6209                 glGenTextures(1, &m_texture);
6210                 glGenVertexArrays(1, &m_attribless_vao);
6211
6212                 const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6213                                                                         "const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6214                                                                         "void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6215                 const char* const glsl_fs =
6216                         "#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6217                         "writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6218                         "subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6219                         "  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6220                         "  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6221                         "  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6222                         "subroutine(Brush) void Brush1(ivec2 coord) {" NL
6223                         "  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6224                         "  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6225                         "  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6226                         "  g_brush(ivec2(gl_FragCoord));" NL "}";
6227                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6228
6229                 return NO_ERROR;
6230         }
6231
6232         virtual long Run()
6233         {
6234                 int width  = getWindowWidth();
6235                 int height = getWindowHeight();
6236                 scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6237
6238                 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6239                 glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6240
6241                 glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6242                 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6243                 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6244
6245                 glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6246
6247                 glDrawBuffer(GL_NONE);
6248                 glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6249                 glUseProgram(m_program);
6250                 glBindVertexArray(m_attribless_vao);
6251
6252                 const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6253                                                                         glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6254
6255                 glViewport(0, 0, width, height);
6256                 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6257                 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6258
6259                 std::vector<vec4> data(width * height * 3);
6260                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6261                 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6262
6263                 for (int layer = 0; layer < 3; ++layer)
6264                 {
6265                         for (int h = 0; h < height; ++h)
6266                         {
6267                                 for (int w = 0; w < width; ++w)
6268                                 {
6269                                         const vec4 c = data[layer * width * height + h * width + w];
6270                                         if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6271                                         {
6272                                                 m_context.getTestContext().getLog()
6273                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6274                                                         << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6275                                                 return ERROR;
6276                                         }
6277                                         else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6278                                         {
6279                                                 m_context.getTestContext().getLog()
6280                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6281                                                         << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6282                                                 return ERROR;
6283                                         }
6284                                         else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6285                                         {
6286                                                 m_context.getTestContext().getLog()
6287                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6288                                                         << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6289                                                 return ERROR;
6290                                         }
6291                                 }
6292                         }
6293                 }
6294
6295                 glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6296                 glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6297
6298                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6299                 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6300
6301                 for (int layer = 0; layer < 3; ++layer)
6302                 {
6303                         for (int h = 0; h < height; ++h)
6304                         {
6305                                 for (int w = 0; w < width; ++w)
6306                                 {
6307                                         const vec4 c = data[layer * width * height + h * width + w];
6308                                         if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6309                                         {
6310                                                 m_context.getTestContext().getLog()
6311                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6312                                                         << ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6313                                                 return ERROR;
6314                                         }
6315                                         else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6316                                         {
6317                                                 m_context.getTestContext().getLog()
6318                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6319                                                         << ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6320                                                 return ERROR;
6321                                         }
6322                                         else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6323                                         {
6324                                                 m_context.getTestContext().getLog()
6325                                                         << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6326                                                         << ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6327                                                 return ERROR;
6328                                         }
6329                                 }
6330                         }
6331                 }
6332                 return NO_ERROR;
6333         }
6334
6335         virtual long Cleanup()
6336         {
6337                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6338                 glDrawBuffer(m_draw_buffer);
6339                 glDeleteTextures(1, &m_texture);
6340                 glUseProgram(0);
6341                 glDeleteProgram(m_program);
6342                 glDeleteVertexArrays(1, &m_attribless_vao);
6343                 return NO_ERROR;
6344         }
6345 };
6346 //-----------------------------------------------------------------------------
6347 // 2.4.4 AdvancedSSOPerSample
6348 //-----------------------------------------------------------------------------
6349 class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6350 {
6351         GLuint m_texture;
6352         GLuint m_pipeline;
6353         GLuint m_vao, m_vbo, m_ebo;
6354         GLuint m_vsp, m_store_fsp, m_load_fsp;
6355
6356         virtual long Setup()
6357         {
6358                 m_vao           = 0;
6359                 m_vbo           = 0;
6360                 m_ebo           = 0;
6361                 m_vsp           = 0;
6362                 m_store_fsp = 0;
6363                 m_load_fsp  = 0;
6364                 glGenTextures(1, &m_texture);
6365                 glGenProgramPipelines(1, &m_pipeline);
6366
6367                 return NO_ERROR;
6368         }
6369
6370         virtual long Run()
6371         {
6372                 if (!SupportedSamples(4))
6373                         return NOT_SUPPORTED;
6374
6375                 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6376
6377                 const char* const glsl_vs =
6378                         "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6379                         "  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6380                 const char* const glsl_store_fs =
6381                         "#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6382                         "  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6383                 const char* const glsl_load_fs =
6384                         "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6385                         "layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6386                         "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6387                         "vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6388                 m_vsp           = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6389                 m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6390                 m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6391
6392                 int width  = getWindowWidth();
6393                 int height = getWindowHeight();
6394                 scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6395
6396                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6397                 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6398                 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6399
6400                 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6401                 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6402
6403                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6404
6405                 glClear(GL_COLOR_BUFFER_BIT);
6406                 glViewport(0, 0, width, height);
6407                 glBindVertexArray(m_vao);
6408                 glBindProgramPipeline(m_pipeline);
6409                 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6410
6411                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6412
6413                 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6414                 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6415
6416                 if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6417                 {
6418                         return ERROR;
6419                 }
6420                 return NO_ERROR;
6421         }
6422
6423         virtual long Cleanup()
6424         {
6425                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6426                 glDeleteBuffers(1, &m_vbo);
6427                 glDeleteBuffers(1, &m_ebo);
6428                 glDeleteTextures(1, &m_texture);
6429                 glDeleteProgram(m_vsp);
6430                 glDeleteProgram(m_store_fsp);
6431                 glDeleteProgram(m_load_fsp);
6432                 glDeleteVertexArrays(1, &m_vao);
6433                 glDeleteProgramPipelines(1, &m_pipeline);
6434                 return NO_ERROR;
6435         }
6436 };
6437
6438 //-----------------------------------------------------------------------------
6439 // 2.5 AdvancedCopyImage
6440 //-----------------------------------------------------------------------------
6441 class AdvancedCopyImage : public ShaderImageLoadStoreBase
6442 {
6443         GLuint m_texture[2];
6444         GLuint m_program;
6445         GLuint m_vao, m_vbo, m_ebo;
6446
6447         virtual long Setup()
6448         {
6449                 glGenTextures(2, m_texture);
6450                 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6451
6452                 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6453                                                                         "void main() {" NL "  gl_Position = i_position;" NL "}";
6454                 const char* const glsl_fs =
6455                         "#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6456                         "layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6457                         "  ivec2 coord = ivec2(gl_FragCoord);" NL
6458                         "  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6459                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6460
6461                 return NO_ERROR;
6462         }
6463
6464         virtual long Run()
6465         {
6466                 int width  = getWindowWidth();
6467                 int height = getWindowHeight();
6468                 scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6469
6470                 glUseProgram(m_program);
6471                 glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6472                 glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6473
6474                 std::vector<vec4> data(width * height, vec4(7.0f));
6475                 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6476                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6477                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6478
6479                 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6480                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6481                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6482
6483                 glBindTexture(GL_TEXTURE_2D, 0);
6484
6485                 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6486                 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6487
6488                 glClear(GL_COLOR_BUFFER_BIT);
6489                 glViewport(0, 0, width, height);
6490                 glBindVertexArray(m_vao);
6491                 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6492
6493                 std::vector<vec4> rdata(width * height);
6494                 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6495                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6496
6497                 for (int h = 0; h < height; ++h)
6498                 {
6499                         for (int w = 0; w < width; ++w)
6500                         {
6501                                 if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6502                                 {
6503                                         return ERROR;
6504                                 }
6505                         }
6506                 }
6507                 return NO_ERROR;
6508         }
6509
6510         virtual long Cleanup()
6511         {
6512                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6513                 glUseProgram(0);
6514                 glDeleteBuffers(1, &m_vbo);
6515                 glDeleteBuffers(1, &m_ebo);
6516                 glDeleteTextures(2, m_texture);
6517                 glDeleteProgram(m_program);
6518                 glDeleteVertexArrays(1, &m_vao);
6519                 return NO_ERROR;
6520         }
6521 };
6522 //-----------------------------------------------------------------------------
6523 // 2.6 AdvancedAllMips
6524 //-----------------------------------------------------------------------------
6525 class AdvancedAllMips : public ShaderImageLoadStoreBase
6526 {
6527         GLuint m_texture;
6528         GLuint m_store_program, m_load_program;
6529         GLuint m_vao, m_vbo, m_ebo;
6530
6531         virtual long Setup()
6532         {
6533                 glGenTextures(1, &m_texture);
6534                 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6535
6536                 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6537                                                                         "void main() {" NL "  gl_Position = i_position;" NL "}";
6538                 const char* const glsl_store_fs =
6539                         "#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6540                         "  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6541                         "  discard;" NL "}";
6542                 const char* const glsl_load_fs =
6543                         "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6544                         "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6545                         "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6546                         "    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6547                         "    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6548                 m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6549                 m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6550
6551                 return NO_ERROR;
6552         }
6553
6554         virtual long Run()
6555         {
6556                 glUseProgram(m_store_program);
6557                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6558                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6559                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6560                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6561                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6562                 glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6563                 glUseProgram(0);
6564
6565                 glUseProgram(m_load_program);
6566                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6567                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6568                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6569                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6570                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6571                 glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6572                 glUseProgram(0);
6573
6574                 glBindTexture(GL_TEXTURE_2D, m_texture);
6575                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6576                 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6577                 glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6578                 glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6579                 glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6580                 glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6581                 glBindTexture(GL_TEXTURE_2D, 0);
6582
6583                 glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6584                 glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6585                 glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6586                 glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587                 glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588                 glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589
6590                 glViewport(0, 0, 32, 32);
6591                 glBindVertexArray(m_vao);
6592
6593                 glClear(GL_COLOR_BUFFER_BIT);
6594                 glUseProgram(m_store_program);
6595                 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6596
6597                 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6598
6599                 glUseProgram(m_load_program);
6600                 glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6601
6602                 if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6603                 {
6604                         return ERROR;
6605                 }
6606                 return NO_ERROR;
6607         }
6608
6609         virtual long Cleanup()
6610         {
6611                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
6612                 glUseProgram(0);
6613                 glDeleteBuffers(1, &m_vbo);
6614                 glDeleteBuffers(1, &m_ebo);
6615                 glDeleteTextures(1, &m_texture);
6616                 glDeleteProgram(m_store_program);
6617                 glDeleteProgram(m_load_program);
6618                 glDeleteVertexArrays(1, &m_vao);
6619                 return NO_ERROR;
6620         }
6621 };
6622 //-----------------------------------------------------------------------------
6623 // 2.7 AdvancedCast
6624 //-----------------------------------------------------------------------------
6625 class AdvancedCast : public ShaderImageLoadStoreBase
6626 {
6627         GLuint m_texture[2];
6628         GLuint m_program;
6629         GLuint m_vao, m_vbo, m_ebo;
6630
6631         virtual long Setup()
6632         {
6633                 glGenTextures(2, m_texture);
6634                 CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6635
6636                 const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6637                                                                         "void main() {" NL "  gl_Position = i_position;" NL "}";
6638                 const char* const glsl_fs =
6639                         "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6640                         "layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6641                         "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6642                         "  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6643                         "  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6644                         "  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6645                         "  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6646                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6647
6648                 return NO_ERROR;
6649         }
6650
6651         virtual long Run()
6652         {
6653                 glUseProgram(m_program);
6654                 glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6655                 glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6656
6657                 {
6658                         std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6659                         glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6660                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6661                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6662                                                  &data[0]);
6663
6664                         glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6665                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6666                         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6667                                                  &data[0]);
6668
6669                         glBindTexture(GL_TEXTURE_2D, 0);
6670                 }
6671
6672                 glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6673                 glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6674
6675                 glClear(GL_COLOR_BUFFER_BIT);
6676                 glBindVertexArray(m_vao);
6677                 glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6678
6679                 std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6680                 glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6681                 glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6682                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6683
6684                 for (int h = 0; h < getWindowHeight(); ++h)
6685                 {
6686                         for (int w = 0; w < getWindowWidth(); ++w)
6687                         {
6688                                 const GLubyte c[4] = {
6689                                         data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6690                                         data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6691                                 };
6692                                 if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6693                                 {
6694                                         m_context.getTestContext().getLog()
6695                                                 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6696                                                 << ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6697                                         return ERROR;
6698                                 }
6699                         }
6700                 }
6701
6702                 glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6703                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6704
6705                 for (int h = 0; h < getWindowHeight(); ++h)
6706                 {
6707                         for (int w = 0; w < getWindowWidth(); ++w)
6708                         {
6709                                 const GLubyte c[4] = {
6710                                         data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6711                                         data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6712                                 };
6713                                 if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6714                                 {
6715                                         m_context.getTestContext().getLog()
6716                                                 << tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6717                                                 << ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6718                                         return ERROR;
6719                                 }
6720                         }
6721                 }
6722
6723                 if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6724                 {
6725                         return ERROR;
6726                 }
6727                 return NO_ERROR;
6728         }
6729
6730         virtual long Cleanup()
6731         {
6732                 glUseProgram(0);
6733                 glDeleteBuffers(1, &m_vbo);
6734                 glDeleteBuffers(1, &m_ebo);
6735                 glDeleteTextures(2, m_texture);
6736                 glDeleteProgram(m_program);
6737                 glDeleteVertexArrays(1, &m_vao);
6738                 return NO_ERROR;
6739         }
6740 };
6741
6742 /** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6743  *
6744  *  Steps:
6745  *  - create two textures: "source" and "destination". Fill "source"
6746  *  texture with unique values. Fill "destination" texture with zeros,
6747  *  - prepare a program object that will read texel from "source" image at given
6748  *  coordinates and write its value to "destination" image at same
6749  *  coordinates,
6750  *  - bind "source" and "destination" textures as "source" and "destination"
6751  *  image uniforms,
6752  *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6753  *  corner at 1,1),
6754  *  - verify that texel values in "destination" texture match those in
6755  *  "source" texture (use glGetTexImage).
6756  *
6757  *  Test with 2D R8UI textures with following dimensions:
6758  *  - 16x16,
6759  *  - 16x17,
6760  *  - 17x16,
6761  *  - 17x17,
6762  *  - 16x18,
6763  *  - 18x16,
6764  *  - 18x18,
6765  *  - 19x16,
6766  *  - 16x19,
6767  *  - 19x19.
6768  *
6769  *  Note that default data alignment should cause problems with packing/
6770  *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6771  *  of pixel storage mode have to be changed to one byte alignment.
6772  *
6773  *  Program should consist of vertex and fragment shader. Vertex shader should
6774  *  pass vertex position through. Fragment shader should do imageLoad() and
6775  *  imageStore() operations at coordinates gl_FragCoord.
6776  **/
6777 class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6778 {
6779 private:
6780         /* Structures */
6781         struct TextureDimensions
6782         {
6783                 GLuint m_width;
6784                 GLuint m_height;
6785
6786                 TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6787                 {
6788                 }
6789         };
6790
6791         /* Typedefs */
6792         typedef std::deque<TextureDimensions> TextureDimensionsList;
6793
6794         /* Fields */
6795         GLuint                            m_destination_texture_id;
6796         GLuint                            m_program_id;
6797         TextureDimensionsList m_texture_dimensions;
6798         GLuint                            m_source_texture_id;
6799         GLuint                            m_vertex_array_object_id;
6800         GLuint                            m_vertex_buffer_id;
6801
6802 public:
6803         /* Constructor */
6804         ImageLoadStoreDataAlignmentTest()
6805                 : m_destination_texture_id(0)
6806                 , m_program_id(0)
6807                 , m_source_texture_id(0)
6808                 , m_vertex_array_object_id(0)
6809                 , m_vertex_buffer_id(0)
6810         {
6811                 /* Nothing to be done here */
6812         }
6813
6814         /* Methods inherited from SubcaseBase */
6815         virtual long Setup()
6816         {
6817                 /* Shaders code */
6818                 const char* const vertex_shader_code = "#version 400 core\n"
6819                                                                                            "#extension GL_ARB_shader_image_load_store : require\n"
6820                                                                                            "\n"
6821                                                                                            "precision highp float;\n"
6822                                                                                            "\n"
6823                                                                                            "in vec4 vs_in_position;\n"
6824                                                                                            "\n"
6825                                                                                            "void main()\n"
6826                                                                                            "{\n"
6827                                                                                            "    gl_Position = vs_in_position;\n"
6828                                                                                            "}\n";
6829
6830                 const char* const fragment_shader_code =
6831                         "#version 400 core\n"
6832                         "#extension GL_ARB_shader_image_load_store : require\n"
6833                         "\n"
6834                         "precision highp float;\n"
6835                         "\n"
6836                         "layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6837                         "layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6838                         "\n"
6839                         "void main()\n"
6840                         "{\n"
6841                         "    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6842                         "                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6843                         "\n"
6844                         "    discard;\n"
6845                         "}\n";
6846
6847                 /* Vertex postions for "full screen" quad, made with triangle strip */
6848                 static const GLfloat m_vertex_buffer_data[] = {
6849                         -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6850                         -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6851                         1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6852                         1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6853                 };
6854
6855                 /* Result of BuildProgram operation */
6856                 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6857
6858                 /* Add all tested texture dimensions */
6859                 m_texture_dimensions.push_back(TextureDimensions(16, 16));
6860                 m_texture_dimensions.push_back(TextureDimensions(16, 17));
6861                 m_texture_dimensions.push_back(TextureDimensions(17, 16));
6862                 m_texture_dimensions.push_back(TextureDimensions(17, 17));
6863                 m_texture_dimensions.push_back(TextureDimensions(16, 18));
6864                 m_texture_dimensions.push_back(TextureDimensions(18, 16));
6865                 m_texture_dimensions.push_back(TextureDimensions(18, 18));
6866                 m_texture_dimensions.push_back(TextureDimensions(16, 19));
6867                 m_texture_dimensions.push_back(TextureDimensions(19, 16));
6868                 m_texture_dimensions.push_back(TextureDimensions(19, 19));
6869
6870                 /* Clean previous error */
6871                 glGetError();
6872
6873                 /* Set single-byte data alignment */
6874                 glPixelStorei(GL_PACK_ALIGNMENT, 1);
6875                 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6876                 GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6877
6878                 /* Prepare buffer with vertex positions of "full screen" quad" */
6879                 glGenBuffers(1, &m_vertex_buffer_id);
6880                 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6881
6882                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6883                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6884
6885                 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6886                 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6887
6888                 /* Generate vertex array object */
6889                 glGenVertexArrays(1, &m_vertex_array_object_id);
6890                 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6891
6892                 /* Prepare program object */
6893                 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6894                                                                         fragment_shader_code, &is_program_correct);
6895                 if (false == is_program_correct)
6896                 {
6897                         return ERROR;
6898                 }
6899
6900                 /* Done */
6901                 return NO_ERROR;
6902         }
6903
6904         virtual long Cleanup()
6905         {
6906                 /* Reset OpenGL state */
6907                 glBindBuffer(GL_ARRAY_BUFFER, 0);
6908                 glBindTexture(GL_TEXTURE_2D, 0);
6909                 glBindVertexArray(0);
6910                 glUseProgram(0);
6911
6912                 /* Delete program */
6913                 if (0 != m_program_id)
6914                 {
6915                         glDeleteProgram(m_program_id);
6916                         m_program_id = 0;
6917                 }
6918
6919                 /* Delete textures */
6920                 if (0 != m_destination_texture_id)
6921                 {
6922                         glDeleteTextures(1, &m_destination_texture_id);
6923                         m_destination_texture_id = 0;
6924                 }
6925
6926                 if (0 != m_source_texture_id)
6927                 {
6928                         glDeleteTextures(1, &m_source_texture_id);
6929                         m_source_texture_id = 0;
6930                 }
6931
6932                 /* Delete vertex array object */
6933                 if (0 != m_vertex_array_object_id)
6934                 {
6935                         glDeleteVertexArrays(1, &m_vertex_array_object_id);
6936                         m_vertex_array_object_id = 0;
6937                 }
6938
6939                 /* Delete buffer */
6940                 if (0 != m_vertex_buffer_id)
6941                 {
6942                         glDeleteBuffers(1, &m_vertex_buffer_id);
6943                         m_vertex_buffer_id = 0;
6944                 }
6945
6946                 /* Done */
6947                 return NO_ERROR;
6948         }
6949
6950         virtual long Run()
6951         {
6952                 bool result = true;
6953
6954                 /* For each dimension */
6955                 for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6956                          ++it)
6957                 {
6958                         /* Prepare "source" and "destination" textures */
6959                         GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6960                                                                 "Create2DR8UIDestinationTexture");
6961                         GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6962                                                                 "Create2DR8UISourceTexture");
6963
6964                         /* Copy texture data with imageLoad() and imageStore() operations */
6965                         Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6966
6967                         /* Compare "source" and "destination" textures */
6968                         if (false ==
6969                                 Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6970                         {
6971                                 m_context.getTestContext().getLog()
6972                                         << tcu::TestLog::Message
6973                                         << "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6974                                         << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6975
6976                                 result = false;
6977                         }
6978
6979                         /* Destroy "source" and "destination" textures */
6980                         glDeleteTextures(1, &m_destination_texture_id);
6981                         glDeleteTextures(1, &m_source_texture_id);
6982
6983                         m_destination_texture_id = 0;
6984                         m_source_texture_id              = 0;
6985                 }
6986
6987                 if (false == result)
6988                 {
6989                         return ERROR;
6990                 }
6991
6992                 /* Done */
6993                 return NO_ERROR;
6994         }
6995
6996 private:
6997         /* Private methods */
6998
6999         /** Binds a texture to user-specified image unit and updates relevant sampler uniform
7000          *
7001          * @param program_id   Program object id
7002          * @param texture_id   Texture id
7003          * @param image_unit   Index of image unit
7004          * @param uniform_name Name of image uniform
7005          **/
7006         void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7007         {
7008                 /* Uniform location and invalid value */
7009                 static const GLint invalid_uniform_location = -1;
7010                 GLint                      image_uniform_location   = 0;
7011
7012                 /* Get uniform location */
7013                 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7014                 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7015                 if (invalid_uniform_location == image_uniform_location)
7016                 {
7017                         throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7018                 }
7019
7020                 /* Bind texture to image unit */
7021                 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7022                 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7023
7024                 /* Set uniform to image unit */
7025                 glUniform1i(image_uniform_location, image_unit);
7026                 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7027         }
7028
7029         /** Compare two 2D R8UI textures
7030          *
7031          * @param left_texture_id  Id of "left" texture object
7032          * @param right_texture_id Id of "right" texture object
7033          * @param width            Width of the textures
7034          * @param height           Height of the textures
7035          *
7036          * @return true when texture data is identical, false otherwise
7037          **/
7038         bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7039         {
7040                 /* Size of textures */
7041                 const GLuint texture_data_size = width * height;
7042
7043                 /* Storage for texture data */
7044                 std::vector<GLubyte> left_texture_data;
7045                 std::vector<GLubyte> right_texture_data;
7046
7047                 /* Alocate memory for texture data */
7048                 left_texture_data.resize(texture_data_size);
7049                 right_texture_data.resize(texture_data_size);
7050
7051                 /* Get "left" texture data */
7052                 glBindTexture(GL_TEXTURE_2D, left_texture_id);
7053                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7054
7055                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7056                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7057
7058                 /* Get "right" texture data */
7059                 glBindTexture(GL_TEXTURE_2D, right_texture_id);
7060                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7061
7062                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7063                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7064
7065                 /* Compare texels */
7066                 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7067         }
7068
7069         /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7070          *
7071          * @param destination_texture_id Id of "destination" texture object
7072          * @param source_texture_id      Id of "source" texture object
7073          **/
7074         void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7075         {
7076                 /* Uniform names */
7077                 static const char* const destination_image_uniform_name = "u_destination_image";
7078                 static const char* const source_image_uniform_name              = "u_source_image";
7079
7080                 /* Attribute name */
7081                 static const char* const position_attribute_name = "vs_in_position";
7082
7083                 /* Attribute location and invalid value */
7084                 static const GLint invalid_attribute_location  = -1;
7085                 GLint                      position_attribute_location = 0;
7086
7087                 /* Set current program */
7088                 glUseProgram(m_program_id);
7089                 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7090
7091                 /* Bind vertex array object */
7092                 glBindVertexArray(m_vertex_array_object_id);
7093                 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7094
7095                 /* Bind buffer with quad vertex positions */
7096                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7097                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7098
7099                 /* Set up position attribute */
7100                 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7101                 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7102                 if (invalid_attribute_location == position_attribute_location)
7103                 {
7104                         throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7105                                                                          __LINE__);
7106                 }
7107
7108                 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7109                                                           0 /* stride */, 0);
7110                 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7111
7112                 glEnableVertexAttribArray(position_attribute_location);
7113                 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7114
7115                 /* Set up textures as source and destination images */
7116                 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7117                 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7118
7119                 /* Execute draw */
7120                 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7121                 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7122         }
7123
7124         /** Create 2D R8UI texture and fills it with zeros
7125          *
7126          * @param width          Width of created texture
7127          * @param height         Height of created texture
7128          * @param out_texture_id Id of created texture, not modified if operation fails
7129          *
7130          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7131          **/
7132         GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7133         {
7134                 /* Texture size */
7135                 const GLuint texture_size = width * height;
7136
7137                 /* Prepare storage for texture data */
7138                 std::vector<GLubyte> texture_data;
7139                 texture_data.resize(texture_size);
7140
7141                 /* Set all texels */
7142                 for (GLuint i = 0; i < texture_size; ++i)
7143                 {
7144                         texture_data[i] = 0;
7145                 }
7146
7147                 /* Create texture */
7148                 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7149         }
7150
7151         /** Create 2D R8UI texture and fills it with increasing values, starting from 0
7152          *
7153          * @param width          Width of created texture
7154          * @param height         Height of created texture
7155          * @param out_texture_id Id of created texture, not modified if operation fails
7156          *
7157          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7158          **/
7159         GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7160         {
7161                 /* Texture size */
7162                 const GLuint texture_size = width * height;
7163
7164                 /* Value of texel */
7165                 GLubyte texel_value = 0;
7166
7167                 /* Prepare storage for texture data */
7168                 std::vector<GLubyte> texture_data;
7169                 texture_data.resize(texture_size);
7170
7171                 /* Set all texels */
7172                 for (GLuint i = 0; i < texture_size; ++i)
7173                 {
7174                         texture_data[i] = texel_value++;
7175                 }
7176
7177                 /* Create texture */
7178                 return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7179         }
7180
7181         /** Create 2D R8UI texture and fills it with user-provided data
7182          *
7183          * @param width          Width of created texture
7184          * @param height         Height of created texture
7185          * @param texture_data   Texture data
7186          * @param out_texture_id Id of created texture, not modified if operation fails
7187          *
7188          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7189          **/
7190         GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7191                                                            GLuint& out_texture_id)
7192         {
7193                 GLenum err                = 0;
7194                 GLuint texture_id = 0;
7195
7196                 /* Generate texture */
7197                 glGenTextures(1, &texture_id);
7198                 err = glGetError();
7199                 if (GL_NO_ERROR != err)
7200                 {
7201                         return err;
7202                 }
7203
7204                 /* Bind texture */
7205                 glBindTexture(GL_TEXTURE_2D, texture_id);
7206                 err = glGetError();
7207                 if (GL_NO_ERROR != err)
7208                 {
7209                         glDeleteTextures(1, &texture_id);
7210                         return err;
7211                 }
7212
7213                 /* Allocate storage and fill texture */
7214                 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7215                                          GL_UNSIGNED_BYTE, &texture_data[0]);
7216                 err = glGetError();
7217                 if (GL_NO_ERROR != err)
7218                 {
7219                         glDeleteTextures(1, &texture_id);
7220                         return err;
7221                 }
7222
7223                 /* Make texture complete */
7224                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7225                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7226                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7227                 err = glGetError();
7228                 if (GL_NO_ERROR != err)
7229                 {
7230                         glDeleteTextures(1, &texture_id);
7231                         return err;
7232                 }
7233
7234                 /* Set out_texture_id */
7235                 out_texture_id = texture_id;
7236
7237                 /* Done */
7238                 return GL_NO_ERROR;
7239         }
7240 };
7241
7242 /** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7243  *
7244  *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7245  *
7246  *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7247  *  | Type           | Dimensions |
7248  *  | 2D_ARRAY       | 64x64x6    |
7249  *  | 3D             | 64x64x6    |
7250  *  | CUBE_MAP       | 64         |
7251  *  | CUBE_MAP_ARRAY | 64x3       |
7252  *
7253  *  Use RGBA8 format. All layers shall be tested.
7254  *
7255  *  Program should consist of vertex and fragment shader. Vertex shader should
7256  *  pass vertex position through. Fragment shader should do imageLoad() and
7257  *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7258  *  use image2D as image type.
7259  **/
7260 class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7261 {
7262 private:
7263         /* Structures */
7264         struct TextureShapeDefinition
7265         {
7266                 GLuint m_edge;
7267                 GLuint m_n_elements;
7268                 GLenum m_type;
7269
7270                 TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7271                         : m_edge(edge), m_n_elements(n_elements), m_type(type)
7272                 {
7273                 }
7274         };
7275
7276         /* Typedefs */
7277         typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7278
7279         /* Fields */
7280         GLuint                                     m_destination_texture_id;
7281         GLuint                                     m_program_id;
7282         TextureShapeDefinitionList m_texture_shape_definitions;
7283         GLuint                                     m_source_texture_id;
7284         GLuint                                     m_vertex_array_object_id;
7285         GLuint                                     m_vertex_buffer_id;
7286
7287 public:
7288         /* Constructor */
7289         ImageLoadStoreNonLayeredBindingTest()
7290                 : m_destination_texture_id(0)
7291                 , m_program_id(0)
7292                 , m_source_texture_id(0)
7293                 , m_vertex_array_object_id(0)
7294                 , m_vertex_buffer_id(0)
7295         {
7296                 /* Nothing to be done here */
7297         }
7298
7299         /* Methods inherited from SubcaseBase */
7300         virtual long Setup()
7301         {
7302                 /* Shaders code */
7303                 const char* const vertex_shader_code = "#version 400 core\n"
7304                                                                                            "#extension GL_ARB_shader_image_load_store : require\n"
7305                                                                                            "\n"
7306                                                                                            "precision highp float;\n"
7307                                                                                            "\n"
7308                                                                                            "in vec4 vs_in_position;\n"
7309                                                                                            "\n"
7310                                                                                            "void main()\n"
7311                                                                                            "{\n"
7312                                                                                            "    gl_Position = vs_in_position;\n"
7313                                                                                            "}\n";
7314
7315                 const char* const fragment_shader_code =
7316                         "#version 400 core\n"
7317                         "#extension GL_ARB_shader_image_load_store : require\n"
7318                         "\n"
7319                         "precision highp float;\n"
7320                         "\n"
7321                         "layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7322                         "layout(rgba8) readonly  uniform image2D u_source_image;\n"
7323                         "\n"
7324                         "void main()\n"
7325                         "{\n"
7326                         "    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7327                         "                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7328                         "\n"
7329                         "    discard;\n"
7330                         "}\n";
7331
7332                 /* Vertex postions for "full screen" quad, defined as a triangle strip */
7333                 static const GLfloat m_vertex_buffer_data[] = {
7334                         -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7335                         -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7336                         1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7337                         1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7338                 };
7339
7340                 /* Result of BuildProgram operation */
7341                 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7342
7343                 /* Add all tested texture shapes */
7344                 int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7345                 m_texture_shape_definitions.push_back(
7346                         TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7347                 m_texture_shape_definitions.push_back(
7348                         TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7349                 m_texture_shape_definitions.push_back(
7350                         TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7351                 m_texture_shape_definitions.push_back(
7352                         TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7353
7354                 /* Prepare buffer with vertex positions of "full screen" quad" */
7355                 glGenBuffers(1, &m_vertex_buffer_id);
7356                 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7357
7358                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7359                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7360
7361                 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7362                 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7363
7364                 /* Generate vertex array object */
7365                 glGenVertexArrays(1, &m_vertex_array_object_id);
7366                 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7367
7368                 /* Prepare program object */
7369                 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7370                                                                         fragment_shader_code, &is_program_correct);
7371                 if (false == is_program_correct)
7372                 {
7373                         return ERROR;
7374                 }
7375
7376                 /* Done */
7377                 return NO_ERROR;
7378         }
7379
7380         virtual long Cleanup()
7381         {
7382                 /* Reset OpenGL state */
7383                 glBindBuffer(GL_ARRAY_BUFFER, 0);
7384                 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7385                 glBindTexture(GL_TEXTURE_3D, 0);
7386                 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7387                 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7388                 glBindVertexArray(0);
7389                 glUseProgram(0);
7390
7391                 /* Delete program */
7392                 if (0 != m_program_id)
7393                 {
7394                         glDeleteProgram(m_program_id);
7395                         m_program_id = 0;
7396                 }
7397
7398                 /* Delete textures */
7399                 if (0 != m_destination_texture_id)
7400                 {
7401                         glDeleteTextures(1, &m_destination_texture_id);
7402                         m_destination_texture_id = 0;
7403                 }
7404
7405                 if (0 != m_source_texture_id)
7406                 {
7407                         glDeleteTextures(1, &m_source_texture_id);
7408                         m_source_texture_id = 0;
7409                 }
7410
7411                 /* Delete vertex array object */
7412                 if (0 != m_vertex_array_object_id)
7413                 {
7414                         glDeleteVertexArrays(1, &m_vertex_array_object_id);
7415                         m_vertex_array_object_id = 0;
7416                 }
7417
7418                 /* Delete buffer */
7419                 if (0 != m_vertex_buffer_id)
7420                 {
7421                         glDeleteBuffers(1, &m_vertex_buffer_id);
7422                         m_vertex_buffer_id = 0;
7423                 }
7424
7425                 /* Done */
7426                 return NO_ERROR;
7427         }
7428
7429         virtual long Run()
7430         {
7431                 bool result = true;
7432
7433                 /* For each shape */
7434                 for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7435                          m_texture_shape_definitions.end() != it; ++it)
7436                 {
7437                         const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7438
7439                         /* Prepare "source" and "destination" textures */
7440                         GLU_EXPECT_NO_ERROR(
7441                                 CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7442                                 "Create2DR8UIDestinationTexture");
7443                         GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7444                                                                 "Create2DR8UISourceTexture");
7445
7446                         /* Copy texture data with imageLoad() and imageStore() operations */
7447                         CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7448
7449                         /* Compare "source" and "destination" textures */
7450                         if (false ==
7451                                 CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7452                         {
7453                                 const char* texture_type = "";
7454                                 switch (it->m_type)
7455                                 {
7456                                 case GL_TEXTURE_2D_ARRAY:
7457                                         texture_type = "2d array";
7458                                         break;
7459                                 case GL_TEXTURE_3D:
7460                                         texture_type = "3d";
7461                                         break;
7462                                 case GL_TEXTURE_CUBE_MAP:
7463                                         texture_type = "Cube map";
7464                                         break;
7465                                 case GL_TEXTURE_CUBE_MAP_ARRAY:
7466                                         texture_type = "Cube map array";
7467                                         break;
7468                                 }
7469
7470                                 m_context.getTestContext().getLog()
7471                                         << tcu::TestLog::Message
7472                                         << "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7473                                         << ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7474
7475                                 result = false;
7476                         }
7477
7478                         /* Destroy "source" and "destination" textures */
7479                         glDeleteTextures(1, &m_destination_texture_id);
7480                         glDeleteTextures(1, &m_source_texture_id);
7481
7482                         m_destination_texture_id = 0;
7483                         m_source_texture_id              = 0;
7484                 }
7485
7486                 if (false == result)
7487                 {
7488                         return ERROR;
7489                 }
7490
7491                 /* Done */
7492                 return NO_ERROR;
7493         }
7494
7495 private:
7496         /* Private methods */
7497
7498         /** Binds a texture to user-specified image unit and update relevant sampler uniform
7499          *
7500          * @param program_id   Program object id
7501          * @param texture_id   Texture id
7502          * @param image_unit   Index of image unit
7503          * @param layer        Index of layer bound to unit
7504          * @param uniform_name Name of image uniform
7505          **/
7506         void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7507                                                         const char* uniform_name)
7508         {
7509                 static const GLint invalid_uniform_location = -1;
7510                 GLint                      image_uniform_location   = 0;
7511
7512                 /* Get uniform location */
7513                 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7514                 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7515                 if (invalid_uniform_location == image_uniform_location)
7516                 {
7517                         throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7518                 }
7519
7520                 /* Bind texture to image unit */
7521                 glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7522                                                    GL_RGBA8);
7523                 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7524
7525                 /* Set uniform to image unit */
7526                 glUniform1i(image_uniform_location, image_unit);
7527                 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7528         }
7529
7530         /** Compare two 2D R8UI textures
7531          *
7532          * @param left_texture_id  Id of "left" texture object
7533          * @param right_texture_id Id of "right" texture object
7534          * @param edge             Length of texture edge
7535          * @param n_layers         Number of layers to compare
7536          * @param type             Type of texture
7537          *
7538          * @return true when texture data is found identical, false otherwise
7539          **/
7540         bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7541                                                           GLenum type)
7542         {
7543                 static const GLuint n_components          = 4; /* RGBA */
7544                 const GLuint            texture_data_size = edge * edge * n_layers * n_components;
7545
7546                 /* Storage for texture data */
7547                 std::vector<GLubyte> left_texture_data;
7548                 std::vector<GLubyte> right_texture_data;
7549
7550                 ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7551                 ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7552
7553                 /* Compare texels */
7554                 return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7555         }
7556
7557         /** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7558          *
7559          * @param destination_texture_id Id of "destination" texture object
7560          * @param source_texture_id      Id of "source" texture object
7561          * @param n_layers               Number of layers
7562          **/
7563         void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7564         {
7565                 for (GLuint layer = 0; layer < n_layers; ++layer)
7566                 {
7567                         CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7568                 }
7569         }
7570
7571         /** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7572          *
7573          * @param destination_texture_id Id of "destination" texture object
7574          * @param source_texture_id      Id of "source" texture object
7575          * @param layer                  Index of layer
7576          **/
7577         void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7578         {
7579                 /* Uniform names */
7580                 static const char* const destination_image_uniform_name = "u_destination_image";
7581                 static const char* const source_image_uniform_name              = "u_source_image";
7582
7583                 /* Attribute name */
7584                 static const char* const position_attribute_name = "vs_in_position";
7585
7586                 /* Attribute location and invalid value */
7587                 static const GLint invalid_attribute_location  = -1;
7588                 GLint                      position_attribute_location = 0;
7589
7590                 /* Set current program */
7591                 glUseProgram(m_program_id);
7592                 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7593
7594                 /* Bind vertex array object */
7595                 glBindVertexArray(m_vertex_array_object_id);
7596                 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7597
7598                 /* Bind buffer with quad vertex positions */
7599                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7600                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7601
7602                 /* Set up vertex attribute array for position attribute */
7603                 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7604                 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7605                 if (invalid_attribute_location == position_attribute_location)
7606                 {
7607                         throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7608                                                                          __LINE__);
7609                 }
7610
7611                 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7612                                                           0 /* stride */, 0 /* pointer */);
7613                 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7614
7615                 glEnableVertexAttribArray(position_attribute_location);
7616                 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7617
7618                 /* Set up textures as source and destination image samplers */
7619                 BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7620                                                    destination_image_uniform_name);
7621                 BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7622
7623                 /* Execute draw */
7624                 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7625                 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7626         }
7627
7628         /** Creates RGBA8 texture of given type and fills it with zeros
7629          *
7630          * @param edge           Edge of created texture
7631          * @param n_elements     Number of elements in texture array
7632          * @param target         Target of created texture
7633          * @param out_texture_id Id of created texture, not modified if operation fails
7634          *
7635          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7636          **/
7637         GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7638         {
7639                 /* Constasts to calculate texture size */
7640                 static const GLuint n_components = 4; /* RGBA */
7641                 const GLuint            layer_size   = edge * edge * n_components;
7642                 const GLuint            n_layers         = GetTotalNumberOfLayers(n_elements, target);
7643                 const GLuint            texture_size = layer_size * n_layers;
7644
7645                 /* Prepare storage for texture data */
7646                 std::vector<GLubyte> texture_data;
7647                 texture_data.resize(texture_size);
7648
7649                 /* Set all texels */
7650                 for (GLuint i = 0; i < texture_size; ++i)
7651                 {
7652                         texture_data[i] = 0;
7653                 }
7654
7655                 /* Create texture */
7656                 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7657         }
7658
7659         /** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7660          *
7661          * @param edge           Edge of created texture
7662          * @param n_elements     Number of elements in texture array
7663          * @param target         Target of created texture
7664          * @param out_texture_id Id of created texture, not modified if operation fails
7665          *
7666          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7667          **/
7668         GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7669         {
7670                 /* Constants to calculate texture size */
7671                 static const GLuint n_components = 4; /* RGBA */
7672                 const GLuint            layer_size   = edge * edge * n_components;
7673                 const GLuint            n_layers         = GetTotalNumberOfLayers(n_elements, target);
7674                 const GLuint            texture_size = layer_size * n_layers;
7675
7676                 /* Value of texel */
7677                 GLubyte texel[4] = { 0, 0, 0, 0xaa };
7678
7679                 /* Prepare storage for texture data */
7680                 std::vector<GLubyte> texture_data;
7681                 texture_data.resize(texture_size);
7682
7683                 /* Set all texels */
7684                 for (GLuint layer = 0; layer < n_layers; ++layer)
7685                 {
7686                         const GLuint layer_offset = layer_size * layer;
7687
7688                         texel[2] = static_cast<GLubyte>(layer);
7689
7690                         for (GLuint y = 0; y < edge; ++y)
7691                         {
7692                                 const GLuint line_offset = y * edge * n_components + layer_offset;
7693
7694                                 texel[1] = static_cast<GLubyte>(y);
7695
7696                                 for (GLuint x = 0; x < edge; ++x)
7697                                 {
7698                                         const GLuint texel_offset = x * n_components + line_offset;
7699                                         texel[0]                                  = static_cast<GLubyte>(x);
7700
7701                                         for (GLuint component = 0; component < n_components; ++component)
7702                                         {
7703                                                 texture_data[texel_offset + component] = texel[component];
7704                                         }
7705                                 }
7706                         }
7707                 }
7708
7709                 /* Create texture */
7710                 return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7711         }
7712
7713         /** Creates RGBA8 texture of given type and fills it provided data
7714          *
7715          * @param edge           Edge of created texture
7716          * @param n_elements     Number of elements in texture array
7717          * @param target         Target of created texture
7718          * @param texture_data   Texture data
7719          * @param out_texture_id Id of created texture, not modified if operation fails
7720          *
7721          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7722          **/
7723         GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7724                                                           GLuint& out_texture_id)
7725         {
7726                 GLenum err                = 0;
7727                 GLuint texture_id = 0;
7728
7729                 /* Generate texture */
7730                 glGenTextures(1, &texture_id);
7731                 err = glGetError();
7732                 if (GL_NO_ERROR != err)
7733                 {
7734                         return err;
7735                 }
7736
7737                 /* Bind texture */
7738                 glBindTexture(target, texture_id);
7739                 err = glGetError();
7740                 if (GL_NO_ERROR != err)
7741                 {
7742                         glDeleteTextures(1, &texture_id);
7743                         return err;
7744                 }
7745
7746                 /* Allocate storage and fill texture */
7747                 if (GL_TEXTURE_CUBE_MAP != target)
7748                 {
7749                         glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7750                                                  GL_UNSIGNED_BYTE, &texture_data[0]);
7751                 }
7752                 else
7753                 {
7754                         const GLuint n_components = 4;
7755                         const GLuint layer_size   = edge * edge * n_components;
7756
7757                         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7758                                                  GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7759                         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7760                                                  GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7761                         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7762                                                  GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7763                         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7764                                                  GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7765                         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7766                                                  GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7767                         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7768                                                  GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7769                 }
7770                 err = glGetError();
7771                 if (GL_NO_ERROR != err)
7772                 {
7773                         glDeleteTextures(1, &texture_id);
7774                         return err;
7775                 }
7776
7777                 /* Make texture complete */
7778                 glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7779                 glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7780                 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7781                 err = glGetError();
7782                 if (GL_NO_ERROR != err)
7783                 {
7784                         glDeleteTextures(1, &texture_id);
7785                         return err;
7786                 }
7787
7788                 /* Set out_texture_id */
7789                 out_texture_id = texture_id;
7790
7791                 /* Done */
7792                 return GL_NO_ERROR;
7793         }
7794
7795         /** Extracts texture data
7796          *
7797          * @param texture_id   Id of texture object
7798          * @param edge         Length of texture edge
7799          * @param n_layers     Number of layers
7800          * @param target       Target of texture
7801          * @param texture_data Extracted texture data
7802          **/
7803         void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7804                                                         std::vector<GLubyte>& texture_data)
7805         {
7806                 static const GLuint n_components          = 4; /* RGBA */
7807                 const GLuint            texture_data_size = edge * edge * n_layers * n_components;
7808
7809                 /* Alocate memory for texture data */
7810                 texture_data.resize(texture_data_size);
7811
7812                 /* Bind texture */
7813                 glBindTexture(target, texture_id);
7814                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7815
7816                 /* Get data */
7817                 if (GL_TEXTURE_CUBE_MAP != target)
7818                 {
7819                         glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7820                 }
7821                 else
7822                 {
7823                         const GLuint layer_size = edge * edge * n_components;
7824
7825                         glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7826                         glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7827                         glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7828                         glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7829                         glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7830                         glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7831                 }
7832
7833                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7834         }
7835
7836         /** Get number of layers per single element for given type of texture
7837          *
7838          * @param target Target of texture
7839          *
7840          * @return Number of layers
7841          **/
7842         GLuint GetLayersPerElement(GLenum target)
7843         {
7844                 switch (target)
7845                 {
7846                 case GL_TEXTURE_2D_ARRAY:
7847                 case GL_TEXTURE_3D:
7848                         return 1;
7849                         break;
7850                 case GL_TEXTURE_CUBE_MAP:
7851                 case GL_TEXTURE_CUBE_MAP_ARRAY:
7852                         return 6;
7853                         break;
7854                 default:
7855                         throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7856                         break;
7857                 }
7858         }
7859
7860         /** Get total number of layers in texture of given type and number of array elements
7861          *
7862          * @param n_elements Number of elements in texture array
7863          * @param target     Target of texture
7864          *
7865          * @return Number of layers
7866          **/
7867         GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7868         {
7869                 return GetLayersPerElement(target) * n_elements;
7870         }
7871 };
7872
7873 /** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7874  *
7875  *  Load from incomplete textures should return 0.
7876  *  Store to incomplete textures should be ignored.
7877  *
7878  *  Steps:
7879  *  - create two incomplete textures: "incomplete_source" and
7880  *  "incomplete_destination",
7881  *  - create two complete textures: "complete_source" and
7882  *  "complete_destination",
7883  *  - fill all textures with unique values,
7884  *  - prepare program that will:
7885  *      * load texel from "incomplete_source" and store its value to
7886  *      "complete_destination",
7887  *      * load texel from "complete_source" and store its value to
7888  *      "incomplete_destination".
7889  *  - bind textures to corresponding image uniforms
7890  *  - execute program for all texels,
7891  *  - verify that "incomplete_destination" was not modified and
7892  *  "complete_destination" is filled with zeros.
7893  *
7894  *  Texture is considered incomplete when it has enabled mipmaping (see below)
7895  *  and does not have all mipmap levels defined.  But for the case of Image
7896  *  accessing, it is considered invalid if it is mipmap-incomplete and the
7897  *  level is different to the base level (base-incomplete).
7898  *
7899  *  Creation of incomplete texture:
7900  *  - generate and bind texture object id,
7901  *  - call TexImage2D with <level>: 0,
7902  *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7903  *  sure, it should be initial value),
7904  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7905  *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7906  *  height)).
7907  *
7908  *  Creation of complete texture:
7909  *  - generate and bind texture object id,
7910  *  - call TexImage2D with <level>: 0,
7911  *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7912  *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7913  *
7914  *  Binding:
7915  *  - Set level == base_level for complete destinations.
7916  *  - Set level != base_level for incomplete destinations that are using
7917  *    mipmap-incomplete textures.
7918  *
7919  *  Test with 2D 64x64 RGBA8 textures.
7920  *
7921  *  Program should consist of vertex and fragment shader. Vertex shader should
7922  *  pass vertex position through. Fragment shader should do imageLoad() and
7923  *  imageStore() operations at coordinates gl_FragCoord.
7924  **/
7925 class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7926 {
7927 private:
7928         /* Constants */
7929         /* Magic numbers that will identify textures, which will be used as their
7930          * texel value.
7931          */
7932         static const GLubyte m_complete_destination_magic_number   = 0x11;
7933         static const GLubyte m_complete_source_magic_number                = 0x22;
7934         static const GLubyte m_incomplete_destination_magic_number = 0x33;
7935         static const GLubyte m_incomplete_source_magic_number     = 0x44;
7936
7937         /* Texture edge */
7938         GLuint m_texture_edge;
7939
7940         /* Fields */
7941         GLuint m_complete_destination_texture_id;
7942         GLuint m_complete_source_texture_id;
7943         GLuint m_incomplete_destination_texture_id;
7944         GLuint m_incomplete_source_texture_id;
7945         GLuint m_program_id;
7946         GLuint m_vertex_array_object_id;
7947         GLuint m_vertex_buffer_id;
7948
7949 public:
7950         /* Constructor */
7951         ImageLoadStoreIncompleteTexturesTest()
7952                 : m_texture_edge(0)
7953                 , m_complete_destination_texture_id(0)
7954                 , m_complete_source_texture_id(0)
7955                 , m_incomplete_destination_texture_id(0)
7956                 , m_incomplete_source_texture_id(0)
7957                 , m_program_id(0)
7958                 , m_vertex_array_object_id(0)
7959                 , m_vertex_buffer_id(0)
7960         {
7961                 /* Nothing to be done here */
7962         }
7963
7964         /* Methods inherited from SubcaseBase */
7965         virtual long Setup()
7966         {
7967                 /* Shaders code */
7968                 const char* const vertex_shader_code = "#version 400 core\n"
7969                                                                                            "#extension GL_ARB_shader_image_load_store : require\n"
7970                                                                                            "\n"
7971                                                                                            "precision highp float;\n"
7972                                                                                            "\n"
7973                                                                                            "in vec4 vs_in_position;\n"
7974                                                                                            "\n"
7975                                                                                            "void main()\n"
7976                                                                                            "{\n"
7977                                                                                            "    gl_Position = vs_in_position;\n"
7978                                                                                            "}\n";
7979
7980                 const char* const fragment_shader_code =
7981                         "#version 400 core\n"
7982                         "#extension GL_ARB_shader_image_load_store : require\n"
7983                         "\n"
7984                         "precision highp float;\n"
7985                         "\n"
7986                         "layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7987                         "layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
7988                         "layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7989                         "layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
7990                         "\n"
7991                         "void main()\n"
7992                         "{\n"
7993                         "    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
7994                         "    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7995
7996                         "    imageStore(u_complete_destination_image,\n"
7997                         "               ivec2(gl_FragCoord),\n"
7998                         "               incomplete_loaded_color);\n"
7999                         "    imageStore(u_incomplete_destination_image,\n"
8000                         "               ivec2(gl_FragCoord),\n"
8001                         "               complete_loaded_color);\n"
8002                         "\n"
8003                         "    discard;\n"
8004                         "}\n";
8005
8006                 /* Vertex postions for "full screen" quad, made with triangle strip */
8007                 static const GLfloat m_vertex_buffer_data[] = {
8008                         -1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8009                         -1.0f, 1.0f,  0.0f, 1.0f, /* left top */
8010                         1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
8011                         1.0f,  1.0f,  0.0f, 1.0f, /* right top */
8012                 };
8013
8014                 /* Result of BuildProgram operation */
8015                 bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8016
8017                 /* Clean previous error */
8018                 glGetError();
8019
8020                 m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8021
8022                 /* Prepare textures */
8023                 GLU_EXPECT_NO_ERROR(
8024                         Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8025                         "Create2DRGBA8CompleteTexture");
8026                 GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8027                                                         "Create2DRGBA8CompleteTexture");
8028                 GLU_EXPECT_NO_ERROR(
8029                         Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8030                         "Create2DRGBA8IncompleteTexture");
8031                 GLU_EXPECT_NO_ERROR(
8032                         Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8033                         "Create2DRGBA8IncompleteTexture");
8034
8035                 /* Prepare buffer with vertex positions of "full screen" quad" */
8036                 glGenBuffers(1, &m_vertex_buffer_id);
8037                 GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8038
8039                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8040                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8041
8042                 glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8043                 GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8044
8045                 /* Generate vertex array object */
8046                 glGenVertexArrays(1, &m_vertex_array_object_id);
8047                 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8048
8049                 /* Prepare program object */
8050                 m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8051                                                                         fragment_shader_code, &is_program_correct);
8052
8053                 if (false == is_program_correct)
8054                 {
8055                         return ERROR;
8056                 }
8057
8058                 /* Done */
8059                 return NO_ERROR;
8060         }
8061
8062         virtual long Cleanup()
8063         {
8064                 /* Reset OpenGL state */
8065                 glBindBuffer(GL_ARRAY_BUFFER, 0);
8066                 glBindTexture(GL_TEXTURE_2D, 0);
8067                 glBindVertexArray(0);
8068                 glUseProgram(0);
8069
8070                 /* Delete program */
8071                 if (0 != m_program_id)
8072                 {
8073                         glDeleteProgram(m_program_id);
8074                         m_program_id = 0;
8075                 }
8076
8077                 /* Delete textures */
8078                 if (0 != m_complete_destination_texture_id)
8079                 {
8080                         glDeleteTextures(1, &m_complete_destination_texture_id);
8081                         m_complete_destination_texture_id = 0;
8082                 }
8083
8084                 if (0 != m_complete_source_texture_id)
8085                 {
8086                         glDeleteTextures(1, &m_complete_source_texture_id);
8087                         m_complete_source_texture_id = 0;
8088                 }
8089
8090                 if (0 != m_incomplete_destination_texture_id)
8091                 {
8092                         glDeleteTextures(1, &m_incomplete_destination_texture_id);
8093                         m_incomplete_destination_texture_id = 0;
8094                 }
8095
8096                 if (0 != m_incomplete_source_texture_id)
8097                 {
8098                         glDeleteTextures(1, &m_incomplete_source_texture_id);
8099                         m_incomplete_source_texture_id = 0;
8100                 }
8101
8102                 /* Delete vertex array object */
8103                 if (0 != m_vertex_array_object_id)
8104                 {
8105                         glDeleteVertexArrays(1, &m_vertex_array_object_id);
8106                         m_vertex_array_object_id = 0;
8107                 }
8108
8109                 /* Delete buffer */
8110                 if (0 != m_vertex_buffer_id)
8111                 {
8112                         glDeleteBuffers(1, &m_vertex_buffer_id);
8113                         m_vertex_buffer_id = 0;
8114                 }
8115
8116                 /* Done */
8117                 return NO_ERROR;
8118         }
8119
8120         virtual long Run()
8121         {
8122                 bool result = true;
8123
8124                 /* Copy textures data with imageLoad() and imageStore() operations */
8125                 Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8126                                                         m_complete_source_texture_id, m_incomplete_source_texture_id);
8127
8128                 glMemoryBarrier(GL_ALL_BARRIER_BITS);
8129
8130                 /* Verify that store to "incomplete destination" was ignored */
8131                 if (true ==
8132                         CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8133                 {
8134                         m_context.getTestContext().getLog()
8135                                 << tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8136                                 << tcu::TestLog::EndMessage;
8137
8138                         result = false;
8139                 }
8140
8141                 /* Verify that load from "incomplete source" returned 0 */
8142                 if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8143                 {
8144                         m_context.getTestContext().getLog()
8145                                 << tcu::TestLog::Message
8146                                 << "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8147                                 << tcu::TestLog::EndMessage;
8148
8149                         result = false;
8150                 }
8151
8152                 if (false == result)
8153                 {
8154                         return ERROR;
8155                 }
8156
8157                 /* Done */
8158                 return NO_ERROR;
8159         }
8160
8161 private:
8162         /* Private methods */
8163
8164         /** Bind texture to image unit and sets image uniform to that unit
8165          *
8166          * @param program_id   Program object id
8167          * @param texture_id   Texture id
8168          * @param level        Texture level
8169          * @param image_unit   Index of image unit
8170          * @param uniform_name Name of image uniform
8171          **/
8172         void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8173         {
8174                 /* Uniform location and invalid value */
8175                 static const GLint invalid_uniform_location = -1;
8176                 GLint                      image_uniform_location   = 0;
8177
8178                 /* Get uniform location */
8179                 image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8180                 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8181                 if (invalid_uniform_location == image_uniform_location)
8182                 {
8183                         throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8184                 }
8185
8186                 /* Bind texture to image unit */
8187                 glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8188                 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8189
8190                 /* Set uniform to image unit */
8191                 glUniform1i(image_uniform_location, image_unit);
8192                 GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8193         }
8194
8195         /** Check if texture is filled with black color, zeros
8196          *
8197          * @param texture_id Id of texture object
8198          *
8199          * @return true when texture is fully black, false otherwise
8200          **/
8201         bool CheckIfTextureIsBlack(GLuint texture_id)
8202         {
8203                 /* Constants to calculate size of texture */
8204                 static const GLuint n_components          = 4; /* RGBA */
8205                 const GLuint            texture_data_size = m_texture_edge * m_texture_edge * n_components;
8206
8207                 /* Storage for texture data */
8208                 std::vector<GLubyte> black_texture_data;
8209                 std::vector<GLubyte> texture_data;
8210
8211                 /* Allocate memory */
8212                 black_texture_data.resize(texture_data_size);
8213                 texture_data.resize(texture_data_size);
8214
8215                 /* Set all texels to black */
8216                 for (GLuint i = 0; i < texture_data_size; ++i)
8217                 {
8218                         black_texture_data[i] = 0;
8219                 }
8220
8221                 /* Bind texture */
8222                 glBindTexture(GL_TEXTURE_2D, texture_id);
8223                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8224
8225                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8226                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8227
8228                 /* Compare texels */
8229                 return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8230         }
8231
8232         /** Check if texture was modified
8233          *
8234          * @param texture_id   Id of texture object
8235          * @param nagic_number Magic number that was to create texture
8236          *
8237          * @return true if texture contents match expected values, false otherwise
8238          **/
8239         bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8240         {
8241                 /* Constants to calculate size of texture */
8242                 static const GLuint n_components          = 4; /* RGBA */
8243                 const GLuint            texture_data_size = m_texture_edge * m_texture_edge * n_components;
8244
8245                 /* Storage for texture data */
8246                 std::vector<GLubyte> expected_texture_data;
8247                 std::vector<GLubyte> texture_data;
8248
8249                 /* Allocate memory */
8250                 expected_texture_data.resize(texture_data_size);
8251                 texture_data.resize(texture_data_size);
8252
8253                 /* Prepare expected texels */
8254                 for (GLuint y = 0; y < m_texture_edge; ++y)
8255                 {
8256                         const GLuint line_offset = y * m_texture_edge * n_components;
8257
8258                         for (GLuint x = 0; x < m_texture_edge; ++x)
8259                         {
8260                                 const GLuint texel_offset = x * n_components + line_offset;
8261
8262                                 SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8263                                                  magic_number);
8264                         }
8265                 }
8266
8267                 /* Bind texture */
8268                 glBindTexture(GL_TEXTURE_2D, texture_id);
8269                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8270
8271                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8272                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8273
8274                 /* Compare texels, true when textures are different */
8275                 return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8276         }
8277
8278         /** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8279          *
8280          * @param complete_destination_texture_id   Id of "complete destination" texture object
8281          * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8282          * @param complete_source_texture_id        Id of "complete source" texture object
8283          * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8284          **/
8285         void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8286                                                          GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8287         {
8288                 /* Uniform names */
8289                 static const char* const complete_destination_image_uniform_name   = "u_complete_destination_image";
8290                 static const char* const complete_source_image_uniform_name                = "u_complete_source_image";
8291                 static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8292                 static const char* const incomplete_source_image_uniform_name     = "u_incomplete_source_image";
8293
8294                 /* Attribute name */
8295                 static const char* const position_attribute_name = "vs_in_position";
8296
8297                 /* Attribute location and invalid value */
8298                 static const GLint invalid_attribute_location  = -1;
8299                 GLint                      position_attribute_location = 0;
8300
8301                 /* Set current program */
8302                 glUseProgram(m_program_id);
8303                 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8304
8305                 /* Bind vertex array object */
8306                 glBindVertexArray(m_vertex_array_object_id);
8307                 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8308
8309                 /* Bind buffer with quad vertex positions */
8310                 glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8311                 GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8312
8313                 /* Setup position attribute */
8314                 position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8315                 GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8316                 if (invalid_attribute_location == position_attribute_location)
8317                 {
8318                         throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8319                                                                          __LINE__);
8320                 }
8321
8322                 glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8323                 GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8324
8325                 glEnableVertexAttribArray(position_attribute_location);
8326                 GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8327
8328                 /* Setup textures as source and destination images */
8329                 BindTextureToImage(m_program_id, complete_destination_texture_id,
8330                                                    0 /* texture level */, 0 /* image_unit */,
8331                                                    complete_destination_image_uniform_name);
8332                 BindTextureToImage(m_program_id, complete_source_texture_id,
8333                                                    0 /* texture level */, 1 /* image_unit */,
8334                                                    complete_source_image_uniform_name);
8335                 BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8336                                                    2 /* texture level */, 2 /* image_unit */,
8337                                                    incomplete_destination_image_uniform_name);
8338                 BindTextureToImage(m_program_id, incomplete_source_texture_id,
8339                                                    2 /* texture level */, 3 /* image_unit */,
8340                                                    incomplete_source_image_uniform_name);
8341
8342                 /* Execute draw */
8343                 glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8344                 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8345         }
8346
8347         /** Create complete 2D RGBA8 texture.
8348          *
8349          * @param magic_number   Magic number of texture
8350          * @param out_texture_id Id of created texture, not modified if operation fails
8351          *
8352          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8353          **/
8354         GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8355         {
8356                 /* Constants to calculate size of texture */
8357                 static const GLuint n_components          = 4; /* RGBA */
8358                 const GLuint            texture_data_size = m_texture_edge * m_texture_edge * n_components;
8359
8360                 /* Error code */
8361                 GLenum err = 0;
8362
8363                 /* Texture id */
8364                 GLuint texture_id = 0;
8365
8366                 /* Prepare storage for texture data */
8367                 std::vector<GLubyte> texture_data;
8368                 texture_data.resize(texture_data_size);
8369
8370                 /* Prepare texture data */
8371                 for (GLuint y = 0; y < m_texture_edge; ++y)
8372                 {
8373                         const GLuint line_offset = y * m_texture_edge * n_components;
8374
8375                         for (GLuint x = 0; x < m_texture_edge; ++x)
8376                         {
8377                                 const GLuint texel_offset = x * n_components + line_offset;
8378
8379                                 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8380                         }
8381                 }
8382
8383                 /* Generate texture */
8384                 glGenTextures(1, &texture_id);
8385                 err = glGetError();
8386                 if (GL_NO_ERROR != err)
8387                 {
8388                         return err;
8389                 }
8390
8391                 /* Bind texture */
8392                 glBindTexture(GL_TEXTURE_2D, texture_id);
8393                 err = glGetError();
8394                 if (GL_NO_ERROR != err)
8395                 {
8396                         glDeleteTextures(1, &texture_id);
8397                         return err;
8398                 }
8399
8400                 /* Allocate storage and fill texture */
8401                 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8402                                          GL_UNSIGNED_BYTE, &texture_data[0]);
8403                 err = glGetError();
8404                 if (GL_NO_ERROR != err)
8405                 {
8406                         glDeleteTextures(1, &texture_id);
8407                         return err;
8408                 }
8409
8410                 /* Make texture complete */
8411                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8412                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8413                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8414                 err = glGetError();
8415                 if (GL_NO_ERROR != err)
8416                 {
8417                         glDeleteTextures(1, &texture_id);
8418                         return err;
8419                 }
8420
8421                 /* Set out_texture_id */
8422                 out_texture_id = texture_id;
8423
8424                 /* Done */
8425                 return GL_NO_ERROR;
8426         }
8427
8428         /** Create incomplete 2D RGBA8 texture
8429          *
8430          * @param magic_number   Magic number of texture
8431          * @param out_texture_id Id of created texture, not modified if operation fails
8432          *
8433          * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8434          **/
8435         GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8436         {
8437                 /* Constants to calculate size of texture */
8438                 static const GLuint n_components          = 4; /* RGBA */
8439                 const GLuint            texture_data_size = m_texture_edge * m_texture_edge * n_components;
8440
8441                 /* Error code */
8442                 GLenum err = 0;
8443
8444                 /* Texture id */
8445                 GLuint texture_id = 0;
8446
8447                 /* Prepare storage for texture data */
8448                 std::vector<GLubyte> texture_data;
8449                 texture_data.resize(texture_data_size);
8450
8451                 /* Prepare texture data */
8452                 for (GLuint y = 0; y < m_texture_edge; ++y)
8453                 {
8454                         const GLuint line_offset = y * m_texture_edge * n_components;
8455
8456                         for (GLuint x = 0; x < m_texture_edge; ++x)
8457                         {
8458                                 const GLuint texel_offset = x * n_components + line_offset;
8459
8460                                 SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8461                         }
8462                 }
8463
8464                 /* Generate texture */
8465                 glGenTextures(1, &texture_id);
8466                 err = glGetError();
8467                 if (GL_NO_ERROR != err)
8468                 {
8469                         return err;
8470                 }
8471
8472                 /* Bind texture */
8473                 glBindTexture(GL_TEXTURE_2D, texture_id);
8474                 err = glGetError();
8475                 if (GL_NO_ERROR != err)
8476                 {
8477                         glDeleteTextures(1, &texture_id);
8478                         return err;
8479                 }
8480
8481                 /* Allocate storage and fill texture */
8482                 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8483                                          GL_UNSIGNED_BYTE, &texture_data[0]);
8484                 err = glGetError();
8485                 if (GL_NO_ERROR != err)
8486                 {
8487                         glDeleteTextures(1, &texture_id);
8488                         return err;
8489                 }
8490
8491                 /* Make texture incomplete */
8492                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8493                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8494                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8495                 err = glGetError();
8496                 if (GL_NO_ERROR != err)
8497                 {
8498                         glDeleteTextures(1, &texture_id);
8499                         return err;
8500                 }
8501
8502                 /* Set out_texture_id */
8503                 out_texture_id = texture_id;
8504
8505                 /* Done */
8506                 return GL_NO_ERROR;
8507         }
8508
8509         /** Prepare "unique" texels.
8510          *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8511          *
8512          * @param texel        Storage of texel
8513          * @param x_coordinate X coordiante of texel
8514          * @param y_coordinate Y coordinate of texel
8515          * @param magic_number Magic number of texture
8516          **/
8517         void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8518         {
8519                 texel[0] = x_coordinate;
8520                 texel[1] = y_coordinate;
8521                 texel[2] = magic_number;
8522                 texel[3] = 0xcc;
8523         }
8524 };
8525
8526 /** Test "Refer to the same image unit using multiple uniforms", description follows.
8527  *
8528  * Steps:
8529  * - prepare program object, see details below,
8530  * - prepare 2D R32I texture, width should be equal to the number of image
8531  * uniforms used by program object, height should be 2, fill first row with
8532  * unique values, fill second row with zeros,
8533  * - bind texture to first image unit,
8534  * - set all image uniforms to first image unit,
8535  * - execute program for a single vertex,
8536  * - verify that:
8537  *     - values in first row were negated,
8538  *     - values from first row were copied to second row,
8539  *
8540  * Repeat steps to test all shader stages that support at least 2 image
8541  * uniforms.
8542  *
8543  * Program has to contain all necessary shader stages. Use boilerplate shaders
8544  * for shader stages that are not important for the test.
8545  *
8546  * Tested shader stage should:
8547  * - Use as many different image formats as possible, image formats compatible
8548  * with R32I:
8549  *     * rg16f
8550  *     * r11f_g11f_b10f
8551  *     * r32f
8552  *     * rgb10_a2ui
8553  *     * rgba8ui
8554  *     * rg16ui
8555  *     * r32ui
8556  *     * rgba8i
8557  *     * rg16i
8558  *     * r32i
8559  *     * rgb10_a2
8560  *     * rgba8
8561  *     * rg16
8562  *     * rgba8_snorm
8563  *     * rg16_snorm.
8564  * - Declare maximum allowed number of image uniforms,
8565  *
8566  *     layout(format) uniform gimage2D u_image;
8567  *
8568  * where <format> is selected image format, <gimage2D> is type of 2D image
8569  * compatible with <format> and <u_image> is unique name of uniform.
8570  * Note that image uniforms cannot be declared as array, due to different image
8571  * formats. Therefore separate uniforms have to be used.
8572  * - Include following code snippet:
8573  * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8574  * {
8575  *     vec row_1_coord(i,0);
8576  *     vec row_2_coord(i,1);
8577  *
8578  *     row_1_value = imageLoad(u_image[i], row_1_coord);
8579  *     imageStore(u_image[i], row_1_coord, -row_1_value);
8580  *     imageStore(u_image[i], row_2_coord, row_1_value);
8581  * }
8582  * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8583  * stage.
8584  **/
8585 class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8586 {
8587 private:
8588         /* Types */
8589         /** Details of image format
8590          *
8591          **/
8592         struct imageFormatDetails
8593         {
8594                 typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8595
8596                 const char*                     m_image_format;
8597                 const char*                     m_image_type;
8598                 const char*                     m_color_type;
8599                 GLenum                          m_image_unit_format;
8600                 verificationRoutine m_verification_routine;
8601         };
8602
8603         template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8604         struct Masks
8605         {
8606                 /** Get mask of bits used to store in bit-field
8607                  *
8608                  * @return Mask
8609                  **/
8610                 static inline T RawMask()
8611                 {
8612                         static const T mask = ValueMask() << OFFSET;
8613
8614                         return mask;
8615                 }
8616
8617                 /** Get mask of bits used to store value.
8618                  *
8619                  * @return Mask
8620                  **/
8621                 static inline T ValueMask()
8622                 {
8623                         static const T mask = (1 << SIZE) - 1;
8624
8625                         return mask;
8626                 }
8627
8628                 /** Get offset.
8629                  *
8630                  * @return offset
8631                  **/
8632                 static inline T Offset()
8633                 {
8634                         return OFFSET;
8635                 }
8636         };
8637
8638         template <typename T, GLuint SIZE, GLuint OFFSET>
8639         struct Masks<T, SIZE, OFFSET, false>
8640         {
8641                 /** Get mask of bits used to store in bit-field
8642                  *
8643                  * @return Mask
8644                  **/
8645                 static inline T RawMask()
8646                 {
8647                         DE_ASSERT(DE_FALSE && "Shouldn't be called");
8648                         return 0;
8649                 }
8650
8651                 /** Get mask of bits used to store value.
8652                  *
8653                  * @return Mask
8654                  **/
8655                 static inline T ValueMask()
8656                 {
8657                         DE_ASSERT(DE_FALSE && "Shouldn't be called");
8658                         return 0;
8659                 }
8660
8661                 /** Get offset.
8662                  *
8663                  * @return offset
8664                  **/
8665                 static inline T Offset()
8666                 {
8667                         DE_ASSERT(DE_FALSE && "Shouldn't be called");
8668                         return 0;
8669                 }
8670         };
8671
8672         /** Template class for accessing integer values stored in bit-fields
8673          *
8674          **/
8675         template <typename T, GLuint SIZE, GLuint OFFSET>
8676         class Integer
8677         {
8678         public:
8679                 /** Constructor
8680                  *
8681                  **/
8682                 Integer(T raw) : m_raw(raw)
8683                 {
8684                 }
8685
8686                 /** Extract value from bit-field
8687                  *
8688                  * @return Value
8689                  **/
8690                 T Get() const
8691                 {
8692                         const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8693
8694                         const T bits   = m_raw & mask;
8695                         const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8696
8697                         return result;
8698                 }
8699
8700                 /** Extract value from bit-field and negate it
8701                  *
8702                  * @return Negated value
8703                  **/
8704                 T GetNegated() const
8705                 {
8706                         const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8707                         const T value = Get();
8708
8709                         return Clamp((~value) + 1) & mask;
8710                 }
8711
8712                 T Clamp(T n) const
8713                 {
8714                         const bool isUnsigned = (T(0) < T(-1));
8715                         const T min               = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8716                         const T max               = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8717                         const T x                 = n > max ? max : n;
8718                         return x < min ? min : x;
8719                 }
8720
8721         private:
8722                 T m_raw;
8723         };
8724
8725         /* Enums */
8726         /** Shader stage identification
8727          *
8728          **/
8729         enum shaderStage
8730         {
8731                 fragmentShaderStage                              = 2,
8732                 geometryShaderStage                              = 4,
8733                 tesselationControlShaderStage   = 8,
8734                 tesselationEvalutaionShaderStage = 16,
8735                 vertexShaderStage                                = 32,
8736         };
8737
8738         /** Test result
8739          *
8740          **/
8741         enum testResult
8742         {
8743                 testFailed               = -1,
8744                 testNotSupported = 1,
8745                 testPassed               = 0
8746         };
8747
8748         /* Constants */
8749         static const GLint m_min_required_image_uniforms = 2;
8750
8751         /* Fields */
8752         GLuint m_program_to_test_fs_stage_id;
8753         GLuint m_program_to_test_gs_stage_id;
8754         GLuint m_program_to_test_tcs_stage_id;
8755         GLuint m_program_to_test_tes_stage_id;
8756         GLuint m_program_to_test_vs_stage_id;
8757         GLuint m_texture_to_test_fs_stage_id;
8758         GLuint m_texture_to_test_gs_stage_id;
8759         GLuint m_texture_to_test_tcs_stage_id;
8760         GLuint m_texture_to_test_tes_stage_id;
8761         GLuint m_texture_to_test_vs_stage_id;
8762         GLuint m_vertex_array_object_id;
8763
8764 public:
8765         /* Constructor */
8766         ImageLoadStoreMultipleUniformsTest()
8767                 : m_program_to_test_fs_stage_id(0)
8768                 , m_program_to_test_gs_stage_id(0)
8769                 , m_program_to_test_tcs_stage_id(0)
8770                 , m_program_to_test_tes_stage_id(0)
8771                 , m_program_to_test_vs_stage_id(0)
8772                 , m_texture_to_test_fs_stage_id(0)
8773                 , m_texture_to_test_gs_stage_id(0)
8774                 , m_texture_to_test_tcs_stage_id(0)
8775                 , m_texture_to_test_tes_stage_id(0)
8776                 , m_texture_to_test_vs_stage_id(0)
8777                 , m_vertex_array_object_id(0)
8778         {
8779                 /* Nothing to be done here */
8780         }
8781
8782         /* Methods inherited from SubcaseBase */
8783         virtual long Setup()
8784         {
8785                 /* Prepare programs */
8786                 m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8787                 m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8788                 m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8789                 m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8790                 m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8791
8792                 /* Prepare textures */
8793                 m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8794                 m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8795                 m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8796                 m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8797                 m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8798
8799                 /* Generate vertex array object */
8800                 glGenVertexArrays(1, &m_vertex_array_object_id);
8801                 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8802
8803                 /* Bind vertex array object */
8804                 glBindVertexArray(m_vertex_array_object_id);
8805                 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8806
8807                 /* Set vertices number for patches */
8808                 glPatchParameteri(GL_PATCH_VERTICES, 1);
8809
8810                 /* Done */
8811                 return NO_ERROR;
8812         }
8813
8814         virtual long Cleanup()
8815         {
8816                 glUseProgram(0);
8817
8818                 /* Delete programs */
8819                 if (0 != m_program_to_test_fs_stage_id)
8820                 {
8821                         glDeleteProgram(m_program_to_test_fs_stage_id);
8822                         m_program_to_test_fs_stage_id = 0;
8823                 }
8824
8825                 if (0 != m_program_to_test_gs_stage_id)
8826                 {
8827                         glDeleteProgram(m_program_to_test_gs_stage_id);
8828                         m_program_to_test_gs_stage_id = 0;
8829                 }
8830
8831                 if (0 != m_program_to_test_tcs_stage_id)
8832                 {
8833                         glDeleteProgram(m_program_to_test_tcs_stage_id);
8834                         m_program_to_test_tcs_stage_id = 0;
8835                 }
8836
8837                 if (0 != m_program_to_test_tes_stage_id)
8838                 {
8839                         glDeleteProgram(m_program_to_test_tes_stage_id);
8840                         m_program_to_test_tes_stage_id = 0;
8841                 }
8842
8843                 if (0 != m_program_to_test_vs_stage_id)
8844                 {
8845                         glDeleteProgram(m_program_to_test_vs_stage_id);
8846                         m_program_to_test_vs_stage_id = 0;
8847                 }
8848
8849                 /* Delete textures */
8850                 if (0 != m_texture_to_test_fs_stage_id)
8851                 {
8852                         glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8853                         m_texture_to_test_fs_stage_id = 0;
8854                 }
8855
8856                 if (0 != m_texture_to_test_gs_stage_id)
8857                 {
8858                         glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8859                         m_texture_to_test_gs_stage_id = 0;
8860                 }
8861
8862                 if (0 != m_texture_to_test_tcs_stage_id)
8863                 {
8864                         glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8865                         m_texture_to_test_tcs_stage_id = 0;
8866                 }
8867
8868                 if (0 != m_texture_to_test_tes_stage_id)
8869                 {
8870                         glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8871                         m_texture_to_test_tes_stage_id = 0;
8872                 }
8873
8874                 if (0 != m_texture_to_test_vs_stage_id)
8875                 {
8876                         glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8877                         m_texture_to_test_vs_stage_id = 0;
8878                 }
8879
8880                 /* Delete vertex array object id */
8881                 if (0 != m_vertex_array_object_id)
8882                 {
8883                         glDeleteVertexArrays(1, &m_vertex_array_object_id);
8884                         m_vertex_array_object_id = 0;
8885                 }
8886
8887                 /* Done */
8888                 return NO_ERROR;
8889         }
8890
8891         virtual long Run()
8892         {
8893                 bool result = true;
8894
8895                 if (testFailed == testShaderStage(fragmentShaderStage))
8896                 {
8897                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8898                                                                                                 << tcu::TestLog::EndMessage;
8899
8900                         result = false;
8901                 }
8902
8903                 if (testFailed == testShaderStage(geometryShaderStage))
8904                 {
8905                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8906                                                                                                 << tcu::TestLog::EndMessage;
8907
8908                         result = false;
8909                 }
8910
8911                 if (testFailed == testShaderStage(tesselationControlShaderStage))
8912                 {
8913                         m_context.getTestContext().getLog() << tcu::TestLog::Message
8914                                                                                                 << "Problems with tesselation control shader stage!"
8915                                                                                                 << tcu::TestLog::EndMessage;
8916
8917                         result = false;
8918                 }
8919
8920                 if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8921                 {
8922                         m_context.getTestContext().getLog() << tcu::TestLog::Message
8923                                                                                                 << "Problems with tesselation evaluation shader stage!"
8924                                                                                                 << tcu::TestLog::EndMessage;
8925
8926                         result = false;
8927                 }
8928
8929                 if (testFailed == testShaderStage(vertexShaderStage))
8930                 {
8931                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8932                                                                                                 << tcu::TestLog::EndMessage;
8933
8934                         result = false;
8935                 }
8936
8937                 if (false == result)
8938                 {
8939                         return ERROR;
8940                 }
8941
8942                 /* Done */
8943                 return NO_ERROR;
8944         }
8945
8946 private:
8947         /* Static routines */
8948         /** Provide image format details for given index
8949          *
8950          * @param index       Index
8951          * @param out_details Image format detail instance
8952          **/
8953         static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8954         {
8955                 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8956                         "r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8957                 };
8958
8959                 static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8960                         { "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8961                         { "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8962                           ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8963                         { "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8964                         { "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8965                           ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966                         { "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8967                         { "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8968                         { "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8969                           ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8970                         { "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8971                           ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8972                         { "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8973                           ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8974                         { "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8975                           ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8976                         { "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8977                           ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8978                         { "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8979                         { "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8980                           ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8981                         { "rg16i", "iimage2D", "ivec4", GL_RG16I,
8982                           ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8983                 };
8984
8985                 static const GLuint n_imageUniformFormatDetails =
8986                         sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8987
8988                 if (n_imageUniformFormatDetails <= index)
8989                 {
8990                         out_details = default_format_details;
8991                 }
8992                 else
8993                 {
8994                         out_details = format_details[index];
8995                 }
8996         }
8997
8998         /** Write name of image uniform at given index to output stream
8999          *
9000          * @param stream Output stream
9001          * @param index  Index
9002          **/
9003         static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9004         {
9005                 /* u_image_0 */
9006                 stream << "u_image_" << index;
9007         }
9008
9009         /** Write name of variable used to store value loaded from image at given index to output stream
9010          *
9011          * @param stream Output stream
9012          * @param index  Index
9013          **/
9014         static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9015         {
9016                 /* loaded_value_0 */
9017                 stream << "loaded_value_" << index;
9018         }
9019
9020         /** Write name of variable used to store coordinate of texel at given row to output stream
9021          *
9022          * @param stream Output stream
9023          * @param index  Index of image uniform
9024          * @param row    Row of image
9025          **/
9026         static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9027         {
9028                 /* row_0_coordinates_0 */
9029                 stream << "row_" << row << "_coordinates_" << index;
9030         }
9031
9032         struct imageUniformDeclaration
9033         {
9034                 imageUniformDeclaration(GLuint index) : m_index(index)
9035                 {
9036                 }
9037
9038                 GLuint m_index;
9039         };
9040
9041         /** Write declaration of image uniform at given index to output stream
9042          *
9043          * @param stream                   Output stream
9044          * @param imageUniformDeclaration  Declaration details
9045          *
9046          * @return stream
9047          **/
9048         friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9049         {
9050                 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9051                 getImageUniformDeclarationDetails(declaration.m_index, format_details);
9052
9053                 /* layout(r32f) uniform image2D u_image_0; */
9054                 stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9055
9056                 ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9057
9058                 stream << ";";
9059
9060                 return stream;
9061         }
9062
9063         struct imageLoadCall
9064         {
9065                 imageLoadCall(GLuint index) : m_index(index)
9066                 {
9067                 }
9068
9069                 GLuint m_index;
9070         };
9071
9072         /* Stream operators */
9073         /** Write code that execute imageLoad routine for image at given index to output stream
9074          *
9075          * @param stream Output stream
9076          * @param load   imageLoad call details
9077          *
9078          * @return stream
9079          **/
9080         friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9081         {
9082                 ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9083                 getImageUniformDeclarationDetails(load.m_index, format_details);
9084
9085                 /* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9086                 stream << format_details.m_color_type << " ";
9087
9088                 writeLoadedValueVariableNameToStream(stream, load.m_index);
9089
9090                 stream << " = imageLoad(";
9091
9092                 writeImageUniformNameToStream(stream, load.m_index);
9093
9094                 stream << ", ";
9095
9096                 writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9097
9098                 stream << ");";
9099
9100                 return stream;
9101         }
9102
9103         struct imageStoreCall
9104         {
9105                 imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9106                 {
9107                 }
9108
9109                 GLuint m_index;
9110                 GLuint m_row;
9111         };
9112
9113         /** Write code that execute imageStore to image at given index to output stream
9114          *
9115          * @param stream Output stream
9116          * @param store  imageStore call details
9117          *
9118          * @return stream
9119          **/
9120         friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9121         {
9122                 /* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9123                 stream << "imageStore(";
9124
9125                 writeImageUniformNameToStream(stream, store.m_index);
9126
9127                 stream << ", ";
9128
9129                 writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9130
9131                 if (0 == store.m_row)
9132                 {
9133                         stream << ", -";
9134                 }
9135                 else
9136                 {
9137                         stream << ", ";
9138                 }
9139
9140                 writeLoadedValueVariableNameToStream(stream, store.m_index);
9141                 stream << ");";
9142
9143                 return stream;
9144         }
9145
9146         struct coordinatesVariableDeclaration
9147         {
9148                 coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9149                 {
9150                 }
9151                 GLuint m_index;
9152                 GLuint m_row;
9153         };
9154
9155         /** Write declaration of variable for coordinate at given row to output stream
9156          *
9157          * @param stream      Output stream
9158          * @param declaration Declaration details
9159          *
9160          * @return stream
9161          **/
9162         friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9163         {
9164                 stream << "const ivec2 ";
9165
9166                 writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9167
9168                 stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9169
9170                 return stream;
9171         }
9172
9173         /* Methods */
9174         /** Build program to test specified shader stage
9175          *
9176          * Throws exception in case of any failure
9177          *
9178          * @param stage Stage id
9179          *
9180          * @return Program id
9181          **/
9182         GLuint buildProgramToTestShaderStage(shaderStage stage)
9183         {
9184                 static const char* const boilerplate_fragment_shader_code =
9185                         "#version 400 core\n"
9186                         "#extension GL_ARB_shader_image_load_store : require\n"
9187                         "\n"
9188                         "precision highp float;\n"
9189                         "\n"
9190                         "void main()\n"
9191                         "{\n"
9192                         "    discard;\n"
9193                         "}\n";
9194
9195                 static const char* const boilerplate_tesselation_evaluation_shader_code =
9196                         "#version 400 core\n"
9197                         "#extension GL_ARB_shader_image_load_store : require\n"
9198                         "\n"
9199                         "precision highp float;\n"
9200                         "\n"
9201                         "layout(quads, equal_spacing, ccw) in;\n"
9202                         "\n"
9203                         "void main()\n"
9204                         "{\n"
9205                         "\n"
9206                         "}\n";
9207
9208                 static const char* const boilerplate_vertex_shader_code =
9209                         "#version 400 core\n"
9210                         "#extension GL_ARB_shader_image_load_store : require\n"
9211                         "\n"
9212                         "precision highp float;\n"
9213                         "\n"
9214                         "layout(location = 0) in vec4 i_position;\n"
9215                         "\n"
9216                         "void main()\n"
9217                         "{\n"
9218                         "  gl_Position = i_position;\n"
9219                         "}\n";
9220
9221                 const char* fragment_shader_code                           = boilerplate_fragment_shader_code;
9222                 const char* geometry_shader_code                           = 0;
9223                 bool            is_program_built                                   = true;
9224                 GLuint          program_object_id                                  = 0;
9225                 const char* tesselation_control_shader_code     = 0;
9226                 const char* tesselation_evaluation_shader_code = 0;
9227                 std::string tested_shader_stage_code;
9228                 const char* vertex_shader_code = boilerplate_vertex_shader_code;
9229
9230                 /* Get source code for tested shader stage */
9231                 prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9232
9233                 if (true == tested_shader_stage_code.empty())
9234                 {
9235                         return 0;
9236                 }
9237
9238                 /* Set up source code for all required stages */
9239                 switch (stage)
9240                 {
9241                 case fragmentShaderStage:
9242                         fragment_shader_code = tested_shader_stage_code.c_str();
9243                         break;
9244
9245                 case geometryShaderStage:
9246                         geometry_shader_code = tested_shader_stage_code.c_str();
9247                         break;
9248
9249                 case tesselationControlShaderStage:
9250                         tesselation_control_shader_code = tested_shader_stage_code.c_str();
9251                         tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9252                         break;
9253
9254                 case tesselationEvalutaionShaderStage:
9255                         tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9256                         break;
9257
9258                 case vertexShaderStage:
9259                         vertex_shader_code = tested_shader_stage_code.c_str();
9260                         break;
9261
9262                 default:
9263                         TCU_FAIL("Invalid shader stage");
9264                 }
9265
9266                 /* Build program */
9267                 program_object_id =
9268                         BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9269                                                  geometry_shader_code, fragment_shader_code, &is_program_built);
9270
9271                 /* Check if program was built */
9272                 if (false == is_program_built)
9273                 {
9274                         throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9275                 }
9276
9277                 /* Done */
9278                 return program_object_id;
9279         }
9280
9281         /** Create texture to test given shader stage
9282          *
9283          * Throws exception in case of any failure
9284          *
9285          * @param stage Stage id
9286          *
9287          * @return Texture id
9288          **/
9289         GLuint createTextureToTestShaderStage(shaderStage stage)
9290         {
9291                 GLenum                     error                          = glGetError();
9292                 const GLint                max_image_uniforms = getMaximumImageUniformsForStage(stage);
9293                 GLuint                     texture_id             = 0;
9294                 std::vector<GLint> texture_data;
9295
9296                 const GLsizei height = 2;
9297                 const GLsizei width  = max_image_uniforms;
9298
9299                 if (m_min_required_image_uniforms > max_image_uniforms)
9300                 {
9301                         return 0;
9302                 }
9303
9304                 /* Generate texture id */
9305                 glGenTextures(1, &texture_id);
9306                 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9307
9308                 /* Bind texture */
9309                 glBindTexture(GL_TEXTURE_2D, texture_id);
9310                 error = glGetError();
9311                 if (GL_NO_ERROR != error)
9312                 {
9313                         glDeleteTextures(1, &texture_id);
9314                         GLU_EXPECT_NO_ERROR(error, "BindTexture");
9315                 }
9316
9317                 /* Prepare storage for texture data */
9318                 texture_data.resize(width * height);
9319                 for (GLint i = 0; i < max_image_uniforms; ++i)
9320                 {
9321                         texture_data[i]                 = getExpectedValue(i);
9322                         texture_data[i + width] = 0;
9323                 }
9324
9325                 /* Create first level of texture */
9326                 glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9327                                          &texture_data[0]);
9328                 error = glGetError();
9329                 if (GL_NO_ERROR != error)
9330                 {
9331                         glDeleteTextures(1, &texture_id);
9332                         GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9333                 }
9334
9335                 /* Make texture complete */
9336                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9337                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9338                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9339                 error = glGetError();
9340                 if (GL_NO_ERROR != error)
9341                 {
9342                         glDeleteTextures(1, &texture_id);
9343                         GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9344                 }
9345
9346                 /* Done */
9347                 return texture_id;
9348         }
9349
9350         /** Get value of texel for image at given index
9351          *
9352          * @param index Index of image uniform
9353          *
9354          * @return Value of texel
9355          **/
9356         GLint getExpectedValue(GLint index)
9357         {
9358                 // To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9359                 // we set one bit in the exponent of each component of those pixel format
9360                 return 0x40104200 + index;
9361         }
9362
9363         /** Get name of uniform at given index
9364          *
9365          * @param index    Index of uniform
9366          * @param out_name Name of uniform
9367          **/
9368         void getImageUniformName(GLuint index, std::string& out_name)
9369         {
9370                 std::stringstream stream;
9371
9372                 writeImageUniformNameToStream(stream, index);
9373
9374                 out_name = stream.str();
9375         }
9376
9377         /** Get maximum number of image uniforms allowed for given shader stage
9378          *
9379          * @param stage Stage id
9380          *
9381          * @return Maximum allowed image uniforms
9382          **/
9383         GLint getMaximumImageUniformsForStage(shaderStage stage)
9384         {
9385                 GLint  max_image_uniforms = 0;
9386                 GLenum pname                      = 0;
9387
9388                 switch (stage)
9389                 {
9390                 case fragmentShaderStage:
9391                         pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9392                         break;
9393
9394                 case geometryShaderStage:
9395                         pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9396                         break;
9397
9398                 case tesselationControlShaderStage:
9399                         pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9400                         break;
9401
9402                 case tesselationEvalutaionShaderStage:
9403                         pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9404                         break;
9405
9406                 case vertexShaderStage:
9407                         pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9408                         break;
9409
9410                 default:
9411                         TCU_FAIL("Invalid shader stage");
9412                 }
9413
9414                 glGetIntegerv(pname, &max_image_uniforms);
9415                 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9416
9417                 return max_image_uniforms;
9418         }
9419
9420         /** Prepare source for tested shader stage
9421          *
9422          * @param stage    Stage id
9423          * @param out_code Source code
9424          **/
9425         void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9426         {
9427                 GLint                     max_image_uniforms    = getMaximumImageUniformsForStage(stage);
9428                 const char*               stage_specific_layout = "";
9429                 const char*               stage_specific_predicate = "true";
9430                 std::stringstream stream;
9431
9432                 if (m_min_required_image_uniforms > max_image_uniforms)
9433                 {
9434                         return;
9435                 }
9436
9437                 /* Expected result follows
9438                  *
9439                  * #version 400 core
9440                  * #extension GL_ARB_shader_image_load_store : require
9441                  *
9442                  * precision highp float;
9443                  *
9444                  * stage_specific_layout goes here
9445                  *
9446                  * Uniform declarations go here
9447                  *
9448                  * void main()
9449                  * {
9450                  *     const ivec2 row_0_coordinates(0, 0);
9451                  *     const ivec2 row_1_coordinates(0, 1);
9452                  *
9453                  *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9454                  *
9455                  *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9456                  *
9457                  *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9458                  *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9459                  * }
9460                  */
9461
9462                 /* Get piece of code specific for stage */
9463                 switch (stage)
9464                 {
9465                 case fragmentShaderStage:
9466                         break;
9467
9468                 case geometryShaderStage:
9469                         stage_specific_layout = "layout(points) in;\n"
9470                                                                         "layout(points, max_vertices = 1) out;\n"
9471                                                                         "\n";
9472                         break;
9473
9474                 case tesselationControlShaderStage:
9475                         stage_specific_layout = "layout(vertices = 4) out;\n"
9476                                                                         "\n";
9477                         stage_specific_predicate = "gl_InvocationID == 0";
9478                         break;
9479
9480                 case tesselationEvalutaionShaderStage:
9481                         stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9482                                                                         "\n";
9483                         break;
9484
9485                 case vertexShaderStage:
9486                         break;
9487
9488                 default:
9489                         TCU_FAIL("Invalid shader stage");
9490                 }
9491
9492                 /* Preamble */
9493                 stream << "#version 400 core\n"
9494                                   "#extension GL_ARB_shader_image_load_store : require\n"
9495                                   "\n"
9496                                   "precision highp float;\n"
9497                                   "\n"
9498                            << stage_specific_layout;
9499
9500                 /* Image uniforms declarations */
9501                 for (GLint i = 0; i < max_image_uniforms; ++i)
9502                 {
9503                         stream << imageUniformDeclaration(i) << "\n";
9504                 }
9505
9506                 /* Main opening */
9507                 stream << "\n"
9508                                   "void main()\n"
9509                                   "{\n";
9510
9511                 stream << "    if (" << stage_specific_predicate << ")\n";
9512                 stream << "    {\n";
9513
9514                 /* imageLoad and imageStores for each uniform */
9515                 for (GLint i = 0; i < max_image_uniforms; ++i)
9516                 {
9517                         stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9518                                    << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9519                                    << "\n"
9520                                    << "        " << imageLoadCall(i) << "\n"
9521                                    << "\n"
9522                                    << "        " << imageStoreCall(i, 0) << "\n"
9523                                    << "        " << imageStoreCall(i, 1) << "\n";
9524
9525                         if (max_image_uniforms > i + 1)
9526                         {
9527                                 stream << "\n";
9528                         }
9529                 }
9530
9531                 stream << "    }\n";
9532
9533                 /* Main closing */
9534                 stream << "}\n\n";
9535
9536                 /* Done */
9537                 out_code = stream.str();
9538         }
9539
9540         /** Test given shader stage
9541          *
9542          * @param stage Stage id
9543          *
9544          * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9545          *         testFailed when test result is negative;
9546          *         m_test_passed when test result is positive;
9547          **/
9548         testResult testShaderStage(shaderStage stage)
9549         {
9550                 std::string                image_uniform_name;
9551                 static const GLint invalid_uniform_location = -1;
9552                 const GLint                max_image_uniforms           = getMaximumImageUniformsForStage(stage);
9553                 GLenum                     primitive_mode                       = GL_POINTS;
9554                 GLuint                     program_id                           = 0;
9555                 testResult                 result                                       = testPassed;
9556                 std::vector<GLint> texture_data;
9557                 GLuint                     texture_id = 0;
9558
9559                 static const GLuint height = 2;
9560                 const GLuint            width  = max_image_uniforms;
9561
9562                 const GLuint            positive_value_index = width;
9563                 static const GLuint negated_value_index  = 0;
9564
9565                 if (m_min_required_image_uniforms > max_image_uniforms)
9566                 {
9567                         return testNotSupported;
9568                 }
9569
9570                 /* Select program and texture ids for given stage */
9571                 switch (stage)
9572                 {
9573                 case fragmentShaderStage:
9574                         program_id = m_program_to_test_fs_stage_id;
9575                         texture_id = m_texture_to_test_fs_stage_id;
9576                         break;
9577
9578                 case geometryShaderStage:
9579                         program_id = m_program_to_test_gs_stage_id;
9580                         texture_id = m_texture_to_test_gs_stage_id;
9581                         break;
9582
9583                 case tesselationControlShaderStage:
9584                         primitive_mode = GL_PATCHES;
9585                         program_id       = m_program_to_test_tcs_stage_id;
9586                         texture_id       = m_texture_to_test_tcs_stage_id;
9587                         break;
9588
9589                 case tesselationEvalutaionShaderStage:
9590                         primitive_mode = GL_PATCHES;
9591                         program_id       = m_program_to_test_tes_stage_id;
9592                         texture_id       = m_texture_to_test_tes_stage_id;
9593                         break;
9594
9595                 case vertexShaderStage:
9596                         program_id = m_program_to_test_vs_stage_id;
9597                         texture_id = m_texture_to_test_vs_stage_id;
9598                         break;
9599
9600                 default:
9601                         TCU_FAIL("Invalid shader stage");
9602                 }
9603
9604                 /* Set program */
9605                 glUseProgram(program_id);
9606                 GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9607
9608                 /* Bind texture to image units */
9609                 for (GLint i = 0; i < max_image_uniforms; ++i)
9610                 {
9611                         imageFormatDetails format_details;
9612                         getImageUniformDeclarationDetails(i, format_details);
9613
9614                         glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9615                                                            GL_READ_WRITE, format_details.m_image_unit_format);
9616                         GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9617                 }
9618
9619                 /* Set all image uniforms to corresponding image units */
9620                 for (GLint i = 0; i < max_image_uniforms; ++i)
9621                 {
9622                         /* Get name */
9623                         getImageUniformName(i, image_uniform_name);
9624
9625                         /* Get location */
9626                         GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9627                         GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9628
9629                         if (invalid_uniform_location == image_uniform_location)
9630                         {
9631                                 throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9632                                                                                  __LINE__);
9633                         }
9634
9635                         /* Set uniform value */
9636                         glUniform1i(image_uniform_location, i /* image_unit */);
9637                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9638                 }
9639
9640                 /* Execute draw */
9641                 glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9642                 GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9643
9644                 glMemoryBarrier(GL_ALL_BARRIER_BITS);
9645
9646                 texture_data.resize(width * height);
9647
9648                 /* Get texture data */
9649                 glBindTexture(GL_TEXTURE_2D, texture_id);
9650                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9651
9652                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9653                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9654
9655                 /* Verify each image uniform */
9656                 for (GLint i = 0; i < max_image_uniforms; ++i)
9657                 {
9658                         imageFormatDetails format_details;
9659                         getImageUniformDeclarationDetails(i, format_details);
9660
9661                         if (false ==
9662                                 format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9663                                                                                                           texture_data[negated_value_index + i]))
9664                         {
9665                                 m_context.getTestContext().getLog()
9666                                         << tcu::TestLog::Message << "Invalid result!"
9667                                         << " Image format: " << format_details.m_image_format << " Original value: "
9668                                         << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9669                                         << " Copied value: "
9670                                         << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9671                                         << texture_data[positive_value_index + i] << " Negated value: "
9672                                         << "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9673                                         << texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9674
9675                                 result = testFailed;
9676                         }
9677                 }
9678
9679                 /* Done */
9680                 return result;
9681         }
9682
9683         /** Verifies if original_value, positive_value and negated_value match
9684          *
9685          * @tparam T Type used during verification process, it should match float values by size
9686          *
9687          * @param original_value Original value of texel, used when creating a texture
9688          * @param positive_value Value stored by shader as read
9689          * @param negated_value  Value stored by shader after negation
9690          *
9691          * @return true if values match, false otherwise
9692          **/
9693         template <typename T>
9694         static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9695         {
9696                 if (original_value != positive_value)
9697                 {
9698                         return false;
9699                 }
9700
9701                 static const GLuint n_elements            = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9702                 static const GLuint sign_bit_index      = sizeof(T) * 8 - 1;               /* 7, 15, 31 */
9703                 static const T          sign_bit_mask    = 1 << sign_bit_index;    /* 0x80.. */
9704                 static const T          sign_bit_inv_mask = (T)~sign_bit_mask;             /* 0x7f.. */
9705
9706                 const T* positive_elements = (T*)&positive_value;
9707                 const T* negated_elements  = (T*)&negated_value;
9708
9709                 for (GLuint i = 0; i < n_elements; ++i)
9710                 {
9711                         const T positive_element = positive_elements[i];
9712                         const T negated_element  = negated_elements[i];
9713
9714                         const T positive_sign_bit = positive_element & sign_bit_mask;
9715                         const T negated_sign_bit  = negated_element & sign_bit_mask;
9716
9717                         const T positive_data = positive_element & sign_bit_inv_mask;
9718                         const T negated_data  = negated_element & sign_bit_inv_mask;
9719
9720                         /* Compare data bits */
9721                         if (positive_data != negated_data)
9722                         {
9723                                 return false;
9724                         }
9725
9726                         /* Verify that sign bit is inverted */
9727                         if (positive_sign_bit == negated_sign_bit)
9728                         {
9729                                 return false;
9730                         }
9731                 }
9732
9733                 return true;
9734         }
9735
9736         /** Verifies if original_value, positive_value and negated_value match
9737          *
9738          * @tparam T Type used during verification process, it should match float values by size
9739          *
9740          * @param original_value Original value of texel, used when creating a texture
9741          * @param positive_value Value stored by shader as read
9742          * @param negated_value  Value stored by shader after negation
9743          *
9744          * @return true if values match, false otherwise
9745          **/
9746         template <typename T>
9747         static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9748         {
9749                 if (original_value != positive_value)
9750                 {
9751                         return false;
9752                 }
9753
9754                 static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9755
9756                 const T* positive_elements = (T*)&positive_value;
9757                 const T* negated_elements  = (T*)&negated_value;
9758
9759                 for (GLuint i = 0; i < n_elements; ++i)
9760                 {
9761                         const T positive_element = positive_elements[i];
9762                         const T negated_element  = negated_elements[i];
9763
9764                         /* Compare data bits */
9765                         if (positive_element != -negated_element)
9766                         {
9767                                 return false;
9768                         }
9769                 }
9770
9771                 return true;
9772         }
9773
9774         /** Verifies if original_value, positive_value and negated_value match
9775          *
9776          * @tparam R Number of bits for red channel
9777          * @tparam G Number of bits for green channel
9778          * @tparam B Number of bits for blue channel
9779          * @tparam A Number of bits for alpha channel
9780          *
9781          * @param original_value Original value of texel, used when creating a texture
9782          * @param positive_value Value stored by shader as read
9783          * @param negated_value  Value stored by shader after negation
9784          *
9785          * @return true if values match, false otherwise
9786          **/
9787         template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
9788         static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9789         {
9790                 if (original_value != positive_value)
9791                 {
9792                         return false;
9793                 }
9794
9795                 Integer<T, R, 0> positive_red(positive_value);
9796                 Integer<T, R, 0> negated_red(negated_value);
9797
9798                 Integer<T, G, R> positive_green(positive_value);
9799                 Integer<T, G, R> negated_green(negated_value);
9800
9801                 Integer<T, B, R + G> positive_blue(positive_value);
9802                 Integer<T, B, R + G> negated_blue(negated_value);
9803
9804                 Integer<T, A, R + G + B> positive_alpha(positive_value);
9805                 Integer<T, A, R + G + B> negated_alpha(negated_value);
9806
9807                 if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9808                         ((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9809                         ((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9810                         ((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9811                 {
9812                         return false;
9813                 }
9814
9815                 return true;
9816         }
9817
9818         /** Verifies if original_value, positive_value and negated_value match
9819          *
9820          * @param original_value Original value of texel, used when creating a texture
9821          * @param positive_value Value stored by shader as read
9822          * @param negated_value  Value stored by shader after negation
9823          *
9824          * @return true if values match, false otherwise
9825          **/
9826         static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9827         {
9828                 if (original_value != positive_value)
9829                 {
9830                         return false;
9831                 }
9832
9833                 if (positive_value != -negated_value)
9834                 {
9835                         return false;
9836                 }
9837
9838                 return true;
9839         }
9840
9841         /** Verifies if original_value, positive_value and negated_value match
9842          *
9843          * @param original_value Original value of texel, used when creating a texture
9844          * @param positive_value Value stored by shader as read
9845          * @param negated_value  Value stored by shader after negation
9846          *
9847          * @return true if values match, false otherwise
9848          **/
9849         template <typename T>
9850         static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9851         {
9852                 if (original_value != positive_value)
9853                 {
9854                         return false;
9855                 }
9856
9857                 if (0 != negated_value)
9858                 {
9859                         return false;
9860                 }
9861
9862                 return true;
9863         }
9864 };
9865
9866 /** Test "Early fragment tests" description follows.
9867  *
9868  *  BasicGLSLEarlyFragTests verifies that:
9869  *  - early z test is applied when enabled,
9870  *  - early z test is not applied when disabled.
9871  *
9872  *  Proposed modifications:
9873  *  - verify that early z test does not discard all fragments when enabled,
9874  *  - verify that early stencil test is applied when enabled,
9875  *  - verify that early stencil test does not discard all fragments when
9876  *  enabled,
9877  *  - verify that early stencil test is not applied when disabled.
9878  *
9879  *  Steps:
9880  *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9881  *  shader stage:
9882  *      a) one program should enable early fragment tests
9883  *      ("layout(early_fragment_tests) in;"),
9884  *      b) second program should disable early fragment tests,
9885  *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9886  *  depth-stencil attachments,
9887  *  - prepare 2D texture 64x64 R32F,
9888  *  - enable depth test,
9889  *  - verify that early z test is applied when enabled:
9890  *      - use program enabling early fragment tests,
9891  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9892  *      - fill texture with zeros,
9893  *      - bind texture to image uniform,
9894  *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9895  *      corner at 1,1) at z: 0.75
9896  *      - verify that texture is still filled with zeros,
9897  *  - verify that early z test does not discard all fragments:
9898  *      - use program enabling early fragment tests,
9899  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9900  *      - fill texture with zeros,
9901  *      - bind texture to image uniform,
9902  *      - draw "full screen" quad at z: 0.25
9903  *      - verify that texture is now filled with 1.0,
9904  *  -verify that early z test is not applied when disabled:
9905  *      - use program disabling early fragment tests,
9906  *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9907  *      - fill texture with zeros,
9908  *      - bind texture to image uniform,
9909  *      - draw "full screen" quad at z: 0.75
9910  *      - verify that texture is now filled with 1.0.
9911  *  - disable depth test
9912  *  - enable stencil test
9913  *  - verify that early stencil test is applied when enabled:
9914  *      - use program enabling early fragment tests,
9915  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9916  *      - fill texture with zeros,
9917  *      - set stencil test to:
9918  *          - <func> to GL_LESS,
9919  *          - <ref> to 128,
9920  *          - <mask> 0xffffffff,
9921  *      - bind texture to image uniform,
9922  *      - draw "full screen" quad at z: 0,
9923  *      - verify that texture is still filled with zeros,
9924  *  - verify that early stencil test does not discard all fragments:
9925  *      - use program enabling early fragment tests,
9926  *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9927  *      - fill texture with zeros,
9928  *      - set stencil test to:
9929  *          - <func> to GL_LESS,
9930  *          - <ref> to 0,
9931  *          - <mask> 0xffffffff,
9932  *      - bind texture to image uniform,
9933  *      - draw "full screen" quad at z: 0,
9934  *      - verify that texture is now filled with 1.0,
9935  *  - verify that early stencil test is not applied when disabled:
9936  *      - use program disabling early fragment tests,
9937  *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9938  *      - fill texture with zeros,
9939  *      - set stencil test to:
9940  *          - <func> to GL_LESS,
9941  *          - <ref> to 128,
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  **/
9947 class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9948 {
9949 private:
9950         /* Constants */
9951         GLuint                     m_image_edge;
9952         static const GLint m_invalid_uniform_location = -1;
9953
9954         /* Types */
9955         /** Store id and uniform locations for a single program object
9956          *
9957          **/
9958         struct programDetails
9959         {
9960                 GLint  m_depth_uniform_location;
9961                 GLint  m_image_uniform_location;
9962                 GLuint m_program_id;
9963
9964                 programDetails()
9965                         : m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9966                         , m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9967                         , m_program_id(0)
9968                 {
9969                         /* Nothing to be done here */
9970                 }
9971         };
9972
9973         /* Fileds */
9974         /* Storage for texture data */
9975         std::vector<GLfloat> m_clean_texture_data;
9976         std::vector<GLfloat> m_extracted_texture_data;
9977
9978         /* Program details */
9979         programDetails m_disabled_early_tests;
9980         programDetails m_enabled_early_tests;
9981
9982         /* Ids of GL objects */
9983         GLuint m_color_renderbuffer_id;
9984         GLuint m_depth_stencil_renderbuffer_id;
9985         GLuint m_framebuffer_id;
9986         GLuint m_texture_id;
9987         GLuint m_vertex_array_object_id;
9988
9989 public:
9990         /* Constructor */
9991         ImageLoadStoreEarlyFragmentTestsTest()
9992                 : m_image_edge(0)
9993                 , m_color_renderbuffer_id(0)
9994                 , m_depth_stencil_renderbuffer_id(0)
9995                 , m_framebuffer_id(0)
9996                 , m_texture_id(0)
9997                 , m_vertex_array_object_id(0)
9998         {
9999                 /* Nothing to be done here */
10000         }
10001
10002         /* Methods inherited from SubcaseBase */
10003         virtual long Cleanup()
10004         {
10005                 /* Restore defaults */
10006                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10007                 glBindRenderbuffer(GL_RENDERBUFFER, 0);
10008                 glBindTexture(GL_TEXTURE_2D, 0);
10009                 glBindVertexArray(0);
10010                 glDisable(GL_DEPTH_TEST);
10011                 glDisable(GL_STENCIL_TEST);
10012                 glUseProgram(0);
10013
10014                 /* Delete objects */
10015                 if (0 != m_disabled_early_tests.m_program_id)
10016                 {
10017                         glDeleteProgram(m_disabled_early_tests.m_program_id);
10018                         m_disabled_early_tests.m_program_id = 0;
10019                 }
10020
10021                 if (0 != m_enabled_early_tests.m_program_id)
10022                 {
10023                         glDeleteProgram(m_enabled_early_tests.m_program_id);
10024                         m_enabled_early_tests.m_program_id = 0;
10025                 }
10026
10027                 if (0 != m_color_renderbuffer_id)
10028                 {
10029                         glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10030                         m_color_renderbuffer_id = 0;
10031                 }
10032
10033                 if (0 != m_depth_stencil_renderbuffer_id)
10034                 {
10035                         glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10036                         m_depth_stencil_renderbuffer_id = 0;
10037                 }
10038
10039                 if (0 != m_framebuffer_id)
10040                 {
10041                         glDeleteFramebuffers(1, &m_framebuffer_id);
10042                         m_framebuffer_id = 0;
10043                 }
10044
10045                 if (0 != m_texture_id)
10046                 {
10047                         glDeleteTextures(1, &m_texture_id);
10048                         m_texture_id = 0;
10049                 }
10050
10051                 if (0 != m_vertex_array_object_id)
10052                 {
10053                         glDeleteVertexArrays(1, &m_vertex_array_object_id);
10054                         m_vertex_array_object_id = 0;
10055                 }
10056
10057                 /* Done */
10058                 return NO_ERROR;
10059         }
10060
10061         virtual long Run()
10062         {
10063                 bool result = true;
10064
10065                 /* Bind texture to first image unit */
10066                 glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10067                                                    GL_READ_WRITE, GL_R32F);
10068                 GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10069
10070                 /* Run tests for depth test */
10071                 if (false == testEarlyZ())
10072                 {
10073                         result = false;
10074                 }
10075
10076                 /* Run tests for stencil test */
10077                 if (false == testEarlyStencil())
10078                 {
10079                         result = false;
10080                 }
10081
10082                 /* Return ERROR if any problem was found */
10083                 if (false == result)
10084                 {
10085                         return ERROR;
10086                 }
10087
10088                 /* Done */
10089                 return NO_ERROR;
10090         }
10091
10092         virtual long Setup()
10093         {
10094                 m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10095
10096                 /* Prepare storage for texture data */
10097                 m_clean_texture_data.resize(m_image_edge * m_image_edge);
10098                 m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10099
10100                 /* Prepare programs, framebuffer and texture */
10101                 buildPrograms();
10102                 createFramebuffer();
10103                 createTexture();
10104
10105                 /* Generate vertex array object */
10106                 glGenVertexArrays(1, &m_vertex_array_object_id);
10107                 GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10108
10109                 /* Bind vertex array object */
10110                 glBindVertexArray(m_vertex_array_object_id);
10111                 GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10112
10113                 /* Set clear color */
10114                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10115                 GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10116
10117                 /* Done */
10118                 return NO_ERROR;
10119         }
10120
10121 private:
10122         /** Build two programs: with enabled and disabled early fragment tests
10123          *
10124          **/
10125         void buildPrograms()
10126         {
10127                 static const char* const fragment_shader_with_disabled_early_tests =
10128                         "#version 400 core\n"
10129                         "#extension GL_ARB_shader_image_load_store : require\n"
10130                         "\n"
10131                         "precision highp float;\n"
10132                         "\n"
10133                         "layout(r32f) uniform image2D u_image;\n"
10134                         "\n"
10135                         "void main()\n"
10136                         "{\n"
10137                         "    vec4 color = vec4(1.0, 0, 0, 0);\n"
10138                         "\n"
10139                         "    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10140                         "\n"
10141                         "    discard;\n"
10142                         "}\n\n";
10143
10144                 static const char* const fragment_shader_with_enabled_early_tests =
10145                         "#version 400 core\n"
10146                         "#extension GL_ARB_shader_image_load_store : require\n"
10147                         "\n"
10148                         "precision highp float;\n"
10149                         "\n"
10150                         "layout(early_fragment_tests) in;\n"
10151                         "\n"
10152                         "layout(r32f) uniform image2D u_image;\n"
10153                         "\n"
10154                         "void main()\n"
10155                         "{\n"
10156                         "    vec4 color = vec4(1.0, 0, 0, 0);\n"
10157                         "\n"
10158                         "    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10159                         "\n"
10160                         "    discard;\n"
10161                         "}\n\n";
10162
10163                 static const char* const geometry_shader_code = "#version 400 core\n"
10164                                                                                                                 "#extension GL_ARB_shader_image_load_store : require\n"
10165                                                                                                                 "\n"
10166                                                                                                                 "precision highp float;\n"
10167                                                                                                                 "\n"
10168                                                                                                                 "layout(points)                           in;\n"
10169                                                                                                                 "layout(triangle_strip, max_vertices = 4) out;\n"
10170                                                                                                                 "\n"
10171                                                                                                                 "uniform float u_depth;\n"
10172                                                                                                                 "\n"
10173                                                                                                                 "void main()\n"
10174                                                                                                                 "{\n"
10175                                                                                                                 "    // Left-bottom\n"
10176                                                                                                                 "    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10177                                                                                                                 "    EmitVertex();\n"
10178                                                                                                                 "\n"
10179                                                                                                                 "    // Left-top\n"
10180                                                                                                                 "    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10181                                                                                                                 "    EmitVertex();\n"
10182                                                                                                                 "\n"
10183                                                                                                                 "    // Right-bottom\n"
10184                                                                                                                 "    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10185                                                                                                                 "    EmitVertex();\n"
10186                                                                                                                 "\n"
10187                                                                                                                 "    // Right-top\n"
10188                                                                                                                 "    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10189                                                                                                                 "    EmitVertex();\n"
10190                                                                                                                 "}\n\n";
10191
10192                 static const char* const vertex_shader_code = "#version 400 core\n"
10193                                                                                                           "#extension GL_ARB_shader_image_load_store : require\n"
10194                                                                                                           "\n"
10195                                                                                                           "precision highp float;\n"
10196                                                                                                           "\n"
10197                                                                                                           "void main()\n"
10198                                                                                                           "{\n"
10199                                                                                                           "}\n\n";
10200
10201                 prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10202                                                           m_disabled_early_tests);
10203
10204                 prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10205                                                           m_enabled_early_tests);
10206         }
10207
10208         /** Fill texture with zeros
10209          *
10210          **/
10211         void cleanTexture()
10212         {
10213                 glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10214                                                 GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10215                 GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10216         }
10217
10218         /** Create and bind (draw) framebuffer with color and depth-stencil attachments
10219          *
10220          **/
10221         void createFramebuffer()
10222         {
10223                 /* Generate render buffers */
10224                 glGenRenderbuffers(1, &m_color_renderbuffer_id);
10225                 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10226
10227                 glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10228                 GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10229
10230                 /* Generate and bind framebuffer object */
10231                 glGenFramebuffers(1, &m_framebuffer_id);
10232                 GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10233
10234                 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10235                 GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10236
10237                 /* Prepare color render buffer */
10238                 glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10239                 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10240
10241                 glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10242                 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10243
10244                 /* Set up color attachment */
10245                 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10246                 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10247
10248                 /* Prepare depth-stencil render buffer */
10249                 glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10250                 GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10251
10252                 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10253                 GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10254
10255                 /* Set up depth-stencil attachment */
10256                 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10257                                                                   m_depth_stencil_renderbuffer_id);
10258                 GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10259         }
10260
10261         /** Create 2D R32F texture
10262          *
10263          **/
10264         void createTexture()
10265         {
10266                 glGenTextures(1, &m_texture_id);
10267                 GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10268
10269                 glBindTexture(GL_TEXTURE_2D, m_texture_id);
10270                 GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10271
10272                 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10273                 GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10274         }
10275
10276         /** Extracts red channel from texture and verify if all texels are set to specified value
10277          *
10278          * @param value Expected value
10279          *
10280          * @return true if all texel match expected value, false otherwise
10281          **/
10282         bool isTextureFilledWithValue(GLfloat value)
10283         {
10284                 glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10285                 GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10286
10287                 for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10288                 {
10289                         if (value != m_extracted_texture_data[i])
10290                         {
10291                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10292                                                                                                         << " has invalid value: " << m_extracted_texture_data[i]
10293                                                                                                         << " expected: " << value << tcu::TestLog::EndMessage;
10294
10295                                 return false;
10296                         }
10297                 }
10298
10299                 return true;
10300         }
10301
10302         /** Build program, extract location of uniforms and store results in programDetails instance
10303          *
10304          * Throws tcu::InternalError if uniforms are inactive
10305          *
10306          * @param fragment_shader_code Source of fragment shader
10307          * @param geometry_shader_code Source of geometry shader
10308          * @param vertex_shader_code   Source of vertex shader
10309          * @param out_program_details  Instance of programDetails
10310          **/
10311         void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10312                                                            const char* vertex_shader_code, programDetails& out_program_details)
10313         {
10314                 static const char* const depth_uniform_name = "u_depth";
10315                 static const char* const image_uniform_name = "u_image";
10316                 bool                                     is_program_built   = true;
10317
10318                 GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10319                                                                                  fragment_shader_code, &is_program_built);
10320
10321                 if (false == is_program_built)
10322                 {
10323                         throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10324                 }
10325
10326                 /* Get depth uniform location */
10327                 GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10328                 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10329
10330                 if (m_invalid_uniform_location == depth_uniform_location)
10331                 {
10332                         throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10333                 }
10334
10335                 /* Get image uniform location */
10336                 GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10337                 GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10338
10339                 if (m_invalid_uniform_location == image_uniform_location)
10340                 {
10341                         throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10342                 }
10343
10344                 /* Store results */
10345                 out_program_details.m_depth_uniform_location = depth_uniform_location;
10346                 out_program_details.m_image_uniform_location = image_uniform_location;
10347                 out_program_details.m_program_id                         = program_id;
10348         }
10349
10350         /** Test if early fragment stencil test works as expected.
10351          *
10352          * @return true if successful, false otherwise
10353          **/
10354         bool testEarlyStencil()
10355         {
10356                 bool result = true;
10357
10358                 glEnable(GL_STENCIL_TEST);
10359                 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10360
10361                 glClearDepthf(1.0f);
10362                 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10363
10364                 /* verify that early stencil test is applied when enabled */
10365                 {
10366                         glUseProgram(m_enabled_early_tests.m_program_id);
10367                         GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10368
10369                         glClearStencil(0);
10370                         GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10371
10372                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10373                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10374
10375                         cleanTexture();
10376
10377                         glStencilFunc(GL_LESS, 128, 0xffffffff);
10378                         GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10379
10380                         glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10381                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10382
10383                         glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10384                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10385
10386                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10387                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10388
10389                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10390                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10391
10392                         if (false == isTextureFilledWithValue(0.0f))
10393                         {
10394                                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10395                                                                                                         << "Problem with early stencil test. It is not applied"
10396                                                                                                         << tcu::TestLog::EndMessage;
10397
10398                                 result = false;
10399                         }
10400                 }
10401
10402                 /* verify that early stencil test does not discard all fragments */
10403                 {
10404                         glClearStencil(128);
10405                         GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10406
10407                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10408                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10409
10410                         cleanTexture();
10411
10412                         glStencilFunc(GL_LESS, 0, 0xffffffff);
10413                         GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10414
10415                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10416                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10417
10418                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10419                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10420
10421                         if (false == isTextureFilledWithValue(1.0f))
10422                         {
10423                                 m_context.getTestContext().getLog()
10424                                         << tcu::TestLog::Message
10425                                         << "Problem with early stencil test. It discards fragments, that shall be drawn"
10426                                         << tcu::TestLog::EndMessage;
10427
10428                                 result = false;
10429                         }
10430                 }
10431
10432                 /* verify that early stencil test is not applied when disabled */
10433                 {
10434                         glUseProgram(m_disabled_early_tests.m_program_id);
10435                         GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10436
10437                         glClearStencil(0);
10438                         GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10439
10440                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10441                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10442
10443                         cleanTexture();
10444
10445                         glStencilFunc(GL_LESS, 128, 0xffffffff);
10446                         GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10447
10448                         glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10449                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10450
10451                         glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10452                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10453
10454                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10455                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10456
10457                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10458                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10459
10460                         if (false == isTextureFilledWithValue(1.0f))
10461                         {
10462                                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10463                                                                                                         << "Problem with early stencil test. It is applied when disabled"
10464                                                                                                         << tcu::TestLog::EndMessage;
10465
10466                                 result = false;
10467                         }
10468                 }
10469
10470                 glDisable(GL_STENCIL_TEST);
10471                 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10472
10473                 /* Done */
10474                 return result;
10475         }
10476
10477         /** Test if early fragment depth test works as expected.
10478          *
10479          * @return true if successful, false otherwise
10480          **/
10481         bool testEarlyZ()
10482         {
10483                 bool result = true;
10484
10485                 glEnable(GL_DEPTH_TEST);
10486                 GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10487
10488                 glClearDepthf(0.5f);
10489                 GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10490
10491                 glClearStencil(0);
10492                 GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10493
10494                 /* verify that early z test is applied when enabled */
10495                 {
10496                         glUseProgram(m_enabled_early_tests.m_program_id);
10497                         GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10498
10499                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10500                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10501
10502                         cleanTexture();
10503
10504                         glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10505                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10506
10507                         glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10508                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10509
10510                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10511                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10512
10513                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10514                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10515
10516                         if (false == isTextureFilledWithValue(0.0f))
10517                         {
10518                                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10519                                                                                                         << "Problem with early z test. It is not applied"
10520                                                                                                         << tcu::TestLog::EndMessage;
10521
10522                                 result = false;
10523                         }
10524                 }
10525
10526                 /* verify that early z test does not discard all fragments */
10527                 {
10528                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10529                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10530
10531                         cleanTexture();
10532
10533                         glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10534                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10535
10536                         glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10537                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10538
10539                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10540                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10541
10542                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10543                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10544
10545                         if (false == isTextureFilledWithValue(1.0f))
10546                         {
10547                                 m_context.getTestContext().getLog()
10548                                         << tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10549                                         << tcu::TestLog::EndMessage;
10550
10551                                 result = false;
10552                         }
10553                 }
10554
10555                 /* verify that early z test is not applied when disabled */
10556                 {
10557                         glUseProgram(m_disabled_early_tests.m_program_id);
10558                         GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10559
10560                         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10561                         GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10562
10563                         cleanTexture();
10564
10565                         glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10566                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10567
10568                         glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10569                         GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10570
10571                         glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10572                         GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10573
10574                         glMemoryBarrier(GL_ALL_BARRIER_BITS);
10575                         GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10576
10577                         if (false == isTextureFilledWithValue(1.0f))
10578                         {
10579                                 m_context.getTestContext().getLog() << tcu::TestLog::Message
10580                                                                                                         << "Problem with early z test. It is applied when disabled"
10581                                                                                                         << tcu::TestLog::EndMessage;
10582
10583                                 result = false;
10584                         }
10585                 }
10586
10587                 glDisable(GL_DEPTH_TEST);
10588                 GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10589
10590                 /* Done */
10591                 return result;
10592         }
10593 };
10594
10595 //-----------------------------------------------------------------------------
10596 // 4.1 NegativeUniform
10597 //-----------------------------------------------------------------------------
10598 class NegativeUniform : public ShaderImageLoadStoreBase
10599 {
10600         GLuint m_program;
10601
10602         virtual long Setup()
10603         {
10604                 m_program = 0;
10605                 return NO_ERROR;
10606         }
10607
10608         virtual long Run()
10609         {
10610                 const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10611                                                           "  gl_Position = i_position;" NL "}";
10612                 const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10613                                                           "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10614                                                           "  discard;" NL "}";
10615                 m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10616
10617                 GLint max_image_units;
10618                 glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10619                 glUseProgram(m_program);
10620
10621                 glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10622                 if (glGetError() != GL_INVALID_VALUE)
10623                 {
10624                         m_context.getTestContext().getLog()
10625                                 << tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10626                                 << tcu::TestLog::EndMessage;
10627                         return ERROR;
10628                 }
10629                 glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10630                 if (glGetError() != GL_INVALID_VALUE)
10631                 {
10632                         m_context.getTestContext().getLog()
10633                                 << tcu::TestLog::Message
10634                                 << "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10635                                 << "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10636                         return ERROR;
10637                 }
10638
10639                 GLint i = -3;
10640                 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10641                 if (glGetError() != GL_INVALID_VALUE)
10642                 {
10643                         m_context.getTestContext().getLog()
10644                                 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10645                                 << tcu::TestLog::EndMessage;
10646                         return ERROR;
10647                 }
10648                 i = max_image_units + 1;
10649                 glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10650                 if (glGetError() != GL_INVALID_VALUE)
10651                 {
10652                         m_context.getTestContext().getLog()
10653                                 << tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10654                                                                                         "than or equal to the value of MAX_IMAGE_UNITS."
10655                                 << tcu::TestLog::EndMessage;
10656                         return ERROR;
10657                 }
10658
10659                 glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10660                 if (glGetError() != GL_INVALID_OPERATION)
10661                 {
10662                         m_context.getTestContext().getLog()
10663                                 << tcu::TestLog::Message
10664                                 << "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10665                                 << tcu::TestLog::EndMessage;
10666                         return ERROR;
10667                 }
10668                 glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10669                 if (glGetError() != GL_INVALID_OPERATION)
10670                 {
10671                         m_context.getTestContext().getLog()
10672                                 << tcu::TestLog::Message
10673                                 << "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10674                                 << tcu::TestLog::EndMessage;
10675                         return ERROR;
10676                 }
10677
10678                 {
10679                         glUseProgram(0);
10680
10681                         glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10682                         if (glGetError() != GL_INVALID_VALUE)
10683                         {
10684                                 m_context.getTestContext().getLog()
10685                                         << tcu::TestLog::Message
10686                                         << "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10687                                         << tcu::TestLog::EndMessage;
10688                                 return ERROR;
10689                         }
10690                         glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10691                         if (glGetError() != GL_INVALID_VALUE)
10692                         {
10693                                 m_context.getTestContext().getLog()
10694                                         << tcu::TestLog::Message
10695                                         << "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10696                                            "value of MAX_IMAGE_UNITS."
10697                                         << tcu::TestLog::EndMessage;
10698                                 return ERROR;
10699                         }
10700
10701                         GLint ii = -3;
10702                         glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10703                         if (glGetError() != GL_INVALID_VALUE)
10704                         {
10705                                 m_context.getTestContext().getLog()
10706                                         << tcu::TestLog::Message
10707                                         << "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10708                                         << tcu::TestLog::EndMessage;
10709                                 return ERROR;
10710                         }
10711                         ii = max_image_units + 1;
10712                         glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10713                         if (glGetError() != GL_INVALID_VALUE)
10714                         {
10715                                 m_context.getTestContext().getLog()
10716                                         << tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10717                                                                                                 "is greater than or equal to the value of MAX_IMAGE_UNITS."
10718                                         << tcu::TestLog::EndMessage;
10719                                 return ERROR;
10720                         }
10721
10722                         glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10723                         if (glGetError() != GL_INVALID_OPERATION)
10724                         {
10725                                 m_context.getTestContext().getLog()
10726                                         << tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10727                                                                                                 "location refers to an image variable."
10728                                         << tcu::TestLog::EndMessage;
10729                                 return ERROR;
10730                         }
10731                         glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10732                         if (glGetError() != GL_INVALID_OPERATION)
10733                         {
10734                                 m_context.getTestContext().getLog()
10735                                         << tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10736                                                                                                 "location refers to an image variable."
10737                                         << tcu::TestLog::EndMessage;
10738                                 return ERROR;
10739                         }
10740                 }
10741
10742                 return NO_ERROR;
10743         }
10744
10745         virtual long Cleanup()
10746         {
10747                 glUseProgram(0);
10748                 glDeleteProgram(m_program);
10749                 return NO_ERROR;
10750         }
10751 };
10752 //-----------------------------------------------------------------------------
10753 // 4.2 NegativeBind
10754 //-----------------------------------------------------------------------------
10755 class NegativeBind : public ShaderImageLoadStoreBase
10756 {
10757         virtual long Setup()
10758         {
10759                 return NO_ERROR;
10760         }
10761
10762         virtual long Run()
10763         {
10764                 glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10765                 if (glGetError() != GL_INVALID_VALUE)
10766                 {
10767                         m_context.getTestContext().getLog()
10768                                 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10769                                                                                         "greater than or equal to the value of MAX_IMAGE_UNITS."
10770                                 << tcu::TestLog::EndMessage;
10771                         return ERROR;
10772                 }
10773
10774                 glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10775                 if (glGetError() != GL_INVALID_VALUE)
10776                 {
10777                         m_context.getTestContext().getLog()
10778                                 << tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10779                                                                                         "the name of an existing texture object."
10780                                 << tcu::TestLog::EndMessage;
10781                         return ERROR;
10782                 }
10783
10784                 glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10785                 if (glGetError() != GL_INVALID_VALUE)
10786                 {
10787                         m_context.getTestContext().getLog()
10788                                 << tcu::TestLog::Message
10789                                 << "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10790                                 << tcu::TestLog::EndMessage;
10791                         return ERROR;
10792                 }
10793                 return NO_ERROR;
10794         }
10795
10796         virtual long Cleanup()
10797         {
10798                 return NO_ERROR;
10799         }
10800 };
10801 //-----------------------------------------------------------------------------
10802 // 4.3 NegativeCompileErrors
10803 //-----------------------------------------------------------------------------
10804 class NegativeCompileErrors : public ShaderImageLoadStoreBase
10805 {
10806         virtual long Run()
10807         {
10808                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10809                                          "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10810                                          "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10811                         return ERROR;
10812
10813                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10814                                          "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10815                                          "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10816                         return ERROR;
10817
10818                 if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10819                                          "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10820                                          "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10821                         return ERROR;
10822
10823                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10824                                          "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10825                         return ERROR;
10826
10827                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10828                                          "readonly uniform image2D g_image;" NL "void main() {" NL
10829                                          "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10830                         return ERROR;
10831
10832                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10833                                          "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10834                         return ERROR;
10835
10836                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10837                                          "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10838                         return ERROR;
10839
10840                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10841                                          "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10842                                          "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10843                         return ERROR;
10844
10845                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10846                                          "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10847                                          "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10848                         return ERROR;
10849
10850                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10851                                          "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10852                                          "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10853                         return ERROR;
10854
10855                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10856                                          "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10857                                          "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10858                         return ERROR;
10859
10860                 if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10861                                          "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10862                                          "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10863                                          "}"))
10864                         return ERROR;
10865
10866                 return NO_ERROR;
10867         }
10868
10869         bool Compile(const std::string& source)
10870         {
10871                 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10872
10873                 const char* const src = source.c_str();
10874                 glShaderSource(sh, 1, &src, NULL);
10875                 glCompileShader(sh);
10876
10877                 GLchar log[1024];
10878                 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10879                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10880                                                                                         << log << tcu::TestLog::EndMessage;
10881
10882                 GLint status;
10883                 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10884                 glDeleteShader(sh);
10885
10886                 if (status == GL_TRUE)
10887                 {
10888                         m_context.getTestContext().getLog()
10889                                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10890                         return false;
10891                 }
10892
10893                 return true;
10894         }
10895 };
10896 //-----------------------------------------------------------------------------
10897 // 4.4 NegativeLinkErrors
10898 //-----------------------------------------------------------------------------
10899 class NegativeLinkErrors : public ShaderImageLoadStoreBase
10900 {
10901         virtual long Run()
10902         {
10903                 if (!SupportedInVS(1))
10904                         return NOT_SUPPORTED;
10905
10906                 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10907                                   "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10908                                   "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10909                                   "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10910                                   "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10911                                   "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10912                         return ERROR;
10913
10914                 if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10915                                   "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10916                                   "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10917                                   "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10918                                   "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10919                                   "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10920                         return ERROR;
10921
10922                 return NO_ERROR;
10923         }
10924
10925         bool Link(const std::string& vs, const std::string& fs)
10926         {
10927                 const GLuint p = glCreateProgram();
10928
10929                 const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10930                 glAttachShader(p, vsh);
10931                 glDeleteShader(vsh);
10932                 const char* const vssrc = vs.c_str();
10933                 glShaderSource(vsh, 1, &vssrc, NULL);
10934                 glCompileShader(vsh);
10935
10936                 const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10937                 glAttachShader(p, fsh);
10938                 glDeleteShader(fsh);
10939                 const char* const fssrc = fs.c_str();
10940                 glShaderSource(fsh, 1, &fssrc, NULL);
10941                 glCompileShader(fsh);
10942
10943                 GLint status;
10944                 glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10945                 if (status == GL_FALSE)
10946                 {
10947                         glDeleteProgram(p);
10948                         m_context.getTestContext().getLog()
10949                                 << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10950                         return false;
10951                 }
10952                 glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10953                 if (status == GL_FALSE)
10954                 {
10955                         glDeleteProgram(p);
10956                         m_context.getTestContext().getLog()
10957                                 << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10958                         return false;
10959                 }
10960
10961                 glLinkProgram(p);
10962
10963                 GLchar log[1024];
10964                 glGetProgramInfoLog(p, sizeof(log), NULL, log);
10965                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10966                                                                                         << log << tcu::TestLog::EndMessage;
10967
10968                 glGetProgramiv(p, GL_LINK_STATUS, &status);
10969                 glDeleteProgram(p);
10970
10971                 if (status == GL_TRUE)
10972                 {
10973                         m_context.getTestContext().getLog()
10974                                 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10975                         return false;
10976                 }
10977
10978                 return true;
10979         }
10980 };
10981
10982 /** Negative Test "Active image uniform limits", description follows.
10983  *
10984  *  Program that exceeds resource limits should not compile and/or link.
10985  *
10986  *  Steps:
10987  *  - try to compile and link a program that uses too many image uniforms in
10988  *  fragment shader stage,
10989  *  - try to compile and link a program that uses too many image uniforms in
10990  *  vertex shader stage,
10991  *  - try to compile and link a program that uses too many image uniforms in
10992  *  tessellation control shader stage,
10993  *  - try to compile and link a program that uses too many image uniforms in
10994  *  tessellation evaluation shader stage,
10995  *  - try to compile and link a program that uses too many image uniforms in
10996  *  geometry shader stage,
10997  *  - try to compile and link a program that uses too many image uniforms in all
10998  *  shader stages combined, any single stage should not exceed its limits, this
10999  *  step might be impossible to fulfill.
11000  *
11001  *  Test should use the following declaration of image uniforms:
11002  *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11003  *
11004  *  For cases where limit for single stage is tested, N_UNIFORMS should be
11005  *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11006  *  corresponding to tested shader stage.
11007  *
11008  *  For case where limit for combined stages is tested:
11009  *  - u_image name should be appended with the name of shader stage, like
11010  *  u_image_vertex,
11011  *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11012  *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11013  *  - compilation and linking shall succeed, when sum of all
11014  *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11015  *  gl_MaxCombinedImageUniforms.
11016  *
11017  *  All defined image uniforms have to be active. Each shader stage that declare
11018  *  image uniforms should include following code snippet:
11019  *  value = 1;
11020  *  for (int i = 0; i < N_UNIFORMS; ++i)
11021  *  {
11022  *      value = imageAtomicAdd(u_image[i], coord, value);
11023  *  }
11024  **/
11025 class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11026 {
11027 private:
11028         /* Fields */
11029         /* Results */
11030         bool m_result_for_combined;
11031         bool m_result_for_fragment_shader;
11032         bool m_result_for_geometry_shader;
11033         bool m_result_for_tesselation_control_shader;
11034         bool m_result_for_tesselatioon_evaluation_shader;
11035         bool m_result_for_vertex_shader;
11036
11037 public:
11038         /* Constructor */
11039         ImageLoadStoreUniformLimitsTest()
11040                 : m_result_for_combined(false)
11041                 , m_result_for_fragment_shader(false)
11042                 , m_result_for_geometry_shader(false)
11043                 , m_result_for_tesselation_control_shader(false)
11044                 , m_result_for_tesselatioon_evaluation_shader(false)
11045                 , m_result_for_vertex_shader(false)
11046         {
11047                 /* Nothing to be done */
11048         }
11049
11050         /* Methods inherited from SubcaseBase */
11051         virtual long Cleanup()
11052         {
11053                 /* Done */
11054                 return NO_ERROR;
11055         }
11056
11057         virtual long Run()
11058         {
11059                 m_context.getTestContext().getLog() << tcu::TestLog::Message
11060                                                                                         << "This test tries to build invalid programs, expect error messages about "
11061                                                                                            "exceeded number of active image uniforms"
11062                                                                                         << tcu::TestLog::EndMessage;
11063
11064                 testFragmentShaderStage();
11065                 testGeometryShaderStage();
11066                 testTesselationControlShaderStage();
11067                 testTesselationEvaluationShaderStage();
11068                 testVertexShaderStage();
11069                 testCombinedShaderStages();
11070
11071                 /* Return error if any stage failed */
11072                 if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11073                         (false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11074                         (false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11075                 {
11076                         return ERROR;
11077                 }
11078
11079                 /* Done */
11080                 return NO_ERROR;
11081         }
11082
11083         virtual long Setup()
11084         {
11085                 /* Done */
11086                 return NO_ERROR;
11087         }
11088
11089 private:
11090         /** Test fragment shader stage
11091          *
11092          **/
11093         void testFragmentShaderStage()
11094         {
11095                 static const char* const fragment_shader_code =
11096                         "#version 400 core\n"
11097                         "#extension GL_ARB_shader_image_load_store : require\n"
11098                         "\n"
11099                         "precision highp float;\n"
11100                         "\n"
11101                         "#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11102                         "\n"
11103                         "flat in ivec2 vs_fs_coord;\n"
11104                         "\n"
11105                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11106                         "\n"
11107                         "void main()\n"
11108                         "{\n"
11109                         "    int value = 1;\n"
11110                         "\n"
11111                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11112                         "    {\n"
11113                         "        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11114                         "    }\n"
11115                         "\n"
11116                         "    discard;\n"
11117                         "}\n\n";
11118
11119                 static const char* const vertex_shader_code = "#version 400 core\n"
11120                                                                                                           "#extension GL_ARB_shader_image_load_store : require\n"
11121                                                                                                           "\n"
11122                                                                                                           "precision highp float;\n"
11123                                                                                                           "\n"
11124                                                                                                           "     in  ivec2 vs_in_coord;\n"
11125                                                                                                           "flat out ivec2 vs_fs_coord;\n"
11126                                                                                                           "\n"
11127                                                                                                           "void main()\n"
11128                                                                                                           "{\n"
11129                                                                                                           "    vs_fs_coord = vs_in_coord;\n"
11130                                                                                                           "}\n\n";
11131
11132                 m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11133                                                                                                                 0 /* tesselation_control_shader_code */,
11134                                                                                                                 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11135
11136                 if (false == m_result_for_fragment_shader)
11137                 {
11138                         m_context.getTestContext().getLog()
11139                                 << tcu::TestLog::Message
11140                                 << "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11141                                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11142                                 << fragment_shader_code << tcu::TestLog::EndMessage;
11143                 }
11144         }
11145
11146         /** Test geometry shader stage
11147          *
11148          **/
11149         void testGeometryShaderStage()
11150         {
11151                 static const char* const fragment_shader_code = "#version 400 core\n"
11152                                                                                                                 "#extension GL_ARB_shader_image_load_store : require\n"
11153                                                                                                                 "\n"
11154                                                                                                                 "precision highp float;\n"
11155                                                                                                                 "\n"
11156                                                                                                                 "void main()\n"
11157                                                                                                                 "{\n"
11158                                                                                                                 "    discard;\n"
11159                                                                                                                 "}\n\n";
11160
11161                 static const char* const geometry_shader_code =
11162                         "#version 400 core\n"
11163                         "#extension GL_ARB_shader_image_load_store : require\n"
11164                         "\n"
11165                         "precision highp float;\n"
11166                         "\n"
11167                         "layout(points)                   in;\n"
11168                         "layout(points, max_vertices = 1) out;\n"
11169                         "\n"
11170                         "#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11171                         "\n"
11172                         "in ivec2 vs_gs_coord[];\n"
11173                         "\n"
11174                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11175                         "\n"
11176                         "void main()\n"
11177                         "{\n"
11178                         "    int value = 1;\n"
11179                         "\n"
11180                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11181                         "    {\n"
11182                         "        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11183                         "    }\n"
11184                         "}\n\n";
11185
11186                 static const char* const vertex_shader_code = "#version 400 core\n"
11187                                                                                                           "#extension GL_ARB_shader_image_load_store : require\n"
11188                                                                                                           "\n"
11189                                                                                                           "precision highp float;\n"
11190                                                                                                           "\n"
11191                                                                                                           "in  ivec2 vs_in_coord;\n"
11192                                                                                                           "out ivec2 vs_gs_coord;\n"
11193                                                                                                           "\n"
11194                                                                                                           "void main()\n"
11195                                                                                                           "{\n"
11196                                                                                                           "    vs_gs_coord = vs_in_coord;\n"
11197                                                                                                           "}\n\n";
11198
11199                 m_result_for_geometry_shader =
11200                         !doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11201                                                          0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11202
11203                 if (false == m_result_for_geometry_shader)
11204                 {
11205                         m_context.getTestContext().getLog()
11206                                 << tcu::TestLog::Message
11207                                 << "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11208                                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11209                                 << geometry_shader_code << tcu::TestLog::EndMessage;
11210                 }
11211         }
11212
11213         /** Test tesselation control shader stage
11214          *
11215          **/
11216         void testTesselationControlShaderStage()
11217         {
11218                 static const char* const fragment_shader_code = "#version 400 core\n"
11219                                                                                                                 "#extension GL_ARB_shader_image_load_store : require\n"
11220                                                                                                                 "\n"
11221                                                                                                                 "precision highp float;\n"
11222                                                                                                                 "\n"
11223                                                                                                                 "void main()\n"
11224                                                                                                                 "{\n"
11225                                                                                                                 "    discard;\n"
11226                                                                                                                 "}\n\n";
11227
11228                 static const char* const tesselation_control_shader_code =
11229                         "#version 400 core\n"
11230                         "#extension GL_ARB_shader_image_load_store : require\n"
11231                         "\n"
11232                         "precision highp float;\n"
11233                         "\n"
11234                         "layout(vertices = 4) out;\n"
11235                         "\n"
11236                         "#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11237                         "\n"
11238                         "in ivec2 vs_tcs_coord[];\n"
11239                         "\n"
11240                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11241                         "\n"
11242                         "void main()\n"
11243                         "{\n"
11244                         "    int value = 1;\n"
11245                         "\n"
11246                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11247                         "    {\n"
11248                         "        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11249                         "    }\n"
11250                         "}\n\n";
11251
11252                 static const char* const tesselation_evaluation_shader_code =
11253                         "#version 400 core\n"
11254                         "#extension GL_ARB_shader_image_load_store : require\n"
11255                         "\n"
11256                         "precision highp float;\n"
11257                         "\n"
11258                         "layout(quads, equal_spacing, ccw) in;\n"
11259                         "\n"
11260                         "void main()\n"
11261                         "{\n"
11262                         "}\n";
11263
11264                 static const char* const vertex_shader_code = "#version 400 core\n"
11265                                                                                                           "#extension GL_ARB_shader_image_load_store : require\n"
11266                                                                                                           "\n"
11267                                                                                                           "precision highp float;\n"
11268                                                                                                           "\n"
11269                                                                                                           "in  ivec2 vs_in_coord;\n"
11270                                                                                                           "out ivec2 vs_tcs_coord;\n"
11271                                                                                                           "\n"
11272                                                                                                           "void main()\n"
11273                                                                                                           "{\n"
11274                                                                                                           "    vs_tcs_coord = vs_in_coord;\n"
11275                                                                                                           "}\n\n";
11276
11277                 m_result_for_tesselation_control_shader =
11278                         !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11279                                                          tesselation_evaluation_shader_code, vertex_shader_code);
11280
11281                 if (false == m_result_for_tesselation_control_shader)
11282                 {
11283                         m_context.getTestContext().getLog()
11284                                 << tcu::TestLog::Message
11285                                 << "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11286                                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11287                                 << tesselation_control_shader_code << tcu::TestLog::EndMessage;
11288                 }
11289         }
11290
11291         /** Test teselation evaluation shader stage
11292          *
11293          **/
11294         void testTesselationEvaluationShaderStage()
11295         {
11296                 static const char* const fragment_shader_code = "#version 400 core\n"
11297                                                                                                                 "#extension GL_ARB_shader_image_load_store : require\n"
11298                                                                                                                 "\n"
11299                                                                                                                 "precision highp float;\n"
11300                                                                                                                 "\n"
11301                                                                                                                 "void main()\n"
11302                                                                                                                 "{\n"
11303                                                                                                                 "    discard;\n"
11304                                                                                                                 "}\n\n";
11305
11306                 static const char* const tesselation_evaluation_shader_code =
11307                         "#version 400 core\n"
11308                         "#extension GL_ARB_shader_image_load_store : require\n"
11309                         "\n"
11310                         "precision highp float;\n"
11311                         "\n"
11312                         "layout(quads, equal_spacing, ccw) in;\n"
11313                         "\n"
11314                         "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11315                         "\n"
11316                         "in ivec2 vs_tes_coord[];\n"
11317                         "\n"
11318                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11319                         "\n"
11320                         "void main()\n"
11321                         "{\n"
11322                         "    int value = 1;\n"
11323                         "\n"
11324                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11325                         "    {\n"
11326                         "        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11327                         "    }\n"
11328                         "}\n\n";
11329
11330                 static const char* const vertex_shader_code = "#version 400 core\n"
11331                                                                                                           "#extension GL_ARB_shader_image_load_store : require\n"
11332                                                                                                           "\n"
11333                                                                                                           "precision highp float;\n"
11334                                                                                                           "\n"
11335                                                                                                           "in  ivec2 vs_in_coord;\n"
11336                                                                                                           "out ivec2 vs_tes_coord;\n"
11337                                                                                                           "\n"
11338                                                                                                           "void main()\n"
11339                                                                                                           "{\n"
11340                                                                                                           "    vs_tes_coord = vs_in_coord;\n"
11341                                                                                                           "}\n\n";
11342
11343                 m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11344                         fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11345                         tesselation_evaluation_shader_code, vertex_shader_code);
11346
11347                 if (false == m_result_for_tesselatioon_evaluation_shader)
11348                 {
11349                         m_context.getTestContext().getLog()
11350                                 << tcu::TestLog::Message
11351                                 << "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11352                                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11353                                 << tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11354                 }
11355         }
11356
11357         /** Test vertex shader stage
11358          *
11359          **/
11360         void testVertexShaderStage()
11361         {
11362                 static const char* const fragment_shader_code = "#version 400 core\n"
11363                                                                                                                 "#extension GL_ARB_shader_image_load_store : require\n"
11364                                                                                                                 "\n"
11365                                                                                                                 "precision highp float;\n"
11366                                                                                                                 "\n"
11367                                                                                                                 "void main()\n"
11368                                                                                                                 "{\n"
11369                                                                                                                 "    discard;\n"
11370                                                                                                                 "}\n\n";
11371
11372                 static const char* const vertex_shader_code =
11373                         "#version 400 core\n"
11374                         "#extension GL_ARB_shader_image_load_store : require\n"
11375                         "\n"
11376                         "precision highp float;\n"
11377                         "\n"
11378                         "in ivec2 vs_in_coord;\n"
11379                         "\n"
11380                         "#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11381                         "\n"
11382                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11383                         "\n"
11384                         "void main()\n"
11385                         "{\n"
11386                         "    int value = 1;\n"
11387                         "\n"
11388                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11389                         "    {\n"
11390                         "        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11391                         "    }\n"
11392                         "}\n\n";
11393
11394                 m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11395                                                                                                           0 /* tesselation_control_shader_code */,
11396                                                                                                           0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11397
11398                 if (false == m_result_for_vertex_shader)
11399                 {
11400                         m_context.getTestContext().getLog()
11401                                 << tcu::TestLog::Message
11402                                 << "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11403                                 << " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11404                                 << vertex_shader_code << tcu::TestLog::EndMessage;
11405                 }
11406         }
11407
11408         /** Test combined shader stages
11409          *
11410          **/
11411         void testCombinedShaderStages()
11412         {
11413                 std::string fragment_shader_code =
11414                         "#version 400 core\n"
11415                         "#extension GL_ARB_shader_image_load_store : require\n"
11416                         "\n"
11417                         "precision highp float;\n"
11418                         "\n"
11419                         "#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11420                         "\n"
11421                         "flat in ivec2 gs_fs_coord;\n"
11422                         "\n"
11423                         "layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11424                         "\n"
11425                         "void main()\n"
11426                         "{\n"
11427                         "    int value = 1;\n"
11428                         "\n"
11429                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11430                         "    {\n"
11431                         "        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11432                         "    }\n"
11433                         "\n"
11434                         "    discard;\n"
11435                         "}\n\n";
11436
11437                 std::string geometry_shader_code =
11438                         "#version 400 core\n"
11439                         "#extension GL_ARB_shader_image_load_store : require\n"
11440                         "\n"
11441                         "precision highp float;\n"
11442                         "\n"
11443                         "layout(points)                   in;\n"
11444                         "layout(points, max_vertices = 1) out;\n"
11445                         "\n"
11446                         "#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11447                         "\n"
11448                         "flat in  ivec2 tes_gs_coord[];\n"
11449                         "flat out ivec2 gs_fs_coord;\n"
11450                         "\n"
11451                         "#ifdef IMAGES\n"
11452                         "layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11453                         "#endif\n"
11454                         "\n"
11455                         "void main()\n"
11456                         "{\n"
11457                         "#ifdef IMAGES\n"
11458                         "    int value = 1;\n"
11459                         "\n"
11460                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11461                         "    {\n"
11462                         "        value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11463                         "    }\n"
11464                         "\n"
11465                         "#endif\n"
11466                         "    gs_fs_coord = tes_gs_coord[0];\n"
11467                         "    EmitVertex();\n"
11468                         "}\n\n";
11469
11470                 std::string tesselation_control_shader_code =
11471                         "#version 400 core\n"
11472                         "#extension GL_ARB_shader_image_load_store : require\n"
11473                         "\n"
11474                         "precision highp float;\n"
11475                         "\n"
11476                         "layout(vertices = 4) out;\n"
11477                         "\n"
11478                         "#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11479                         "\n"
11480                         "flat in  ivec2 vs_tcs_coord[];\n"
11481                         "flat out ivec2 tcs_tes_coord[];\n"
11482                         "\n"
11483                         "#ifdef IMAGES\n"
11484                         "layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11485                         "#endif\n"
11486                         "\n"
11487                         "void main()\n"
11488                         "{\n"
11489                         "#ifdef IMAGES\n"
11490                         "    int value = 1;\n"
11491                         "\n"
11492                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11493                         "    {\n"
11494                         "        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11495                         "    }\n"
11496                         "\n"
11497                         "#endif\n"
11498                         "    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11499                         "}\n\n";
11500
11501                 std::string tesselation_evaluation_shader_code =
11502                         "#version 400 core\n"
11503                         "#extension GL_ARB_shader_image_load_store : require\n"
11504                         "\n"
11505                         "precision highp float;\n"
11506                         "\n"
11507                         "layout(quads, equal_spacing, ccw) in;\n"
11508                         "\n"
11509                         "#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11510                         "\n"
11511                         "flat in  ivec2 tcs_tes_coord[];\n"
11512                         "flat out ivec2 tes_gs_coord;\n"
11513                         "\n"
11514                         "#ifdef IMAGES\n"
11515                         "layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11516                         "#endif\n"
11517                         "\n"
11518                         "void main()\n"
11519                         "{\n"
11520                         "#ifdef IMAGES\n"
11521                         "    int value = 1;\n"
11522                         "\n"
11523                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11524                         "    {\n"
11525                         "        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11526                         "    }\n"
11527                         "\n"
11528                         "#endif\n"
11529                         "    tes_gs_coord = tcs_tes_coord[0];\n"
11530                         "}\n\n";
11531
11532                 std::string vertex_shader_code =
11533                         "#version 400 core\n"
11534                         "#extension GL_ARB_shader_image_load_store : require\n"
11535                         "\n"
11536                         "precision highp float;\n"
11537                         "\n"
11538                         "     in  ivec2 vs_in_coord;\n"
11539                         "flat out ivec2 vs_tcs_coord;\n"
11540                         "\n"
11541                         "#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11542                         "\n"
11543                         "#ifdef IMAGES\n"
11544                         "layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11545                         "#endif\n"
11546                         "\n"
11547                         "void main()\n"
11548                         "{\n"
11549                         "#ifdef IMAGES\n"
11550                         "    int value = 1;\n"
11551                         "\n"
11552                         "    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11553                         "    {\n"
11554                         "        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11555                         "    }\n"
11556                         "\n"
11557                         "#endif\n"
11558                         "    vs_tcs_coord = vs_tcs_coord;\n"
11559                         "}\n\n";
11560
11561                 /* Active image uniform limits */
11562                 GLint max_combined_image_uniforms                               = 0;
11563                 GLint max_fragment_image_uniforms                               = 0;
11564                 GLint max_geometry_image_uniforms                               = 0;
11565                 GLint max_tesselation_control_image_uniforms    = 0;
11566                 GLint max_tesselation_evaluation_image_uniforms = 0;
11567                 GLint max_vertex_image_uniforms                                 = 0;
11568
11569                 /* Get limit values */
11570                 glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11571                 glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11572                 glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11573                 glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11574                 glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11575                 glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11576                 GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11577
11578                 if (max_vertex_image_uniforms)
11579                         vertex_shader_code.insert(18, "#define IMAGES\n");
11580                 if (max_geometry_image_uniforms)
11581                         geometry_shader_code.insert(18, "#define IMAGES\n");
11582                 if (max_tesselation_control_image_uniforms)
11583                         tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11584                 if (max_tesselation_evaluation_image_uniforms)
11585                         tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11586
11587                 /* Check if program builds */
11588                 m_result_for_combined =
11589                         !doesProgramLink(fragment_shader_code.c_str(),
11590                                                          geometry_shader_code.c_str(),
11591                                                          tesselation_control_shader_code.c_str(),
11592                                                          tesselation_evaluation_shader_code.c_str(),
11593                                                          vertex_shader_code.c_str());
11594
11595                 /* Result depends on the limit values */
11596                 if (max_combined_image_uniforms >=
11597                         (max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11598                          max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11599                 {
11600                         /* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11601                         m_result_for_combined = !m_result_for_combined;
11602
11603                         if (false == m_result_for_combined)
11604                         {
11605                                 m_context.getTestContext().getLog()
11606                                         << tcu::TestLog::Message << "There was an error while building a program."
11607                                         << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11608                                         << vertex_shader_code << "\nTesselation control shader code:\n"
11609                                         << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11610                                         << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11611                                         << geometry_shader_code << "\nFragment shader code:\n"
11612                                         << fragment_shader_code << tcu::TestLog::EndMessage;
11613                         }
11614                 }
11615                 else
11616                 {
11617                         /* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11618                         if (false == m_result_for_combined)
11619                         {
11620                                 m_context.getTestContext().getLog()
11621                                         << tcu::TestLog::Message
11622                                         << "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11623                                         << " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11624                                         << vertex_shader_code << "\nTesselation control shader code:\n"
11625                                         << tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11626                                         << tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11627                                         << geometry_shader_code << "\nFragment shader code:\n"
11628                                         << fragment_shader_code << tcu::TestLog::EndMessage;
11629                         }
11630                 }
11631         }
11632
11633         /** Check if program builds successfully
11634          *
11635          * @param fragment_shader_code               Source code for fragment shader stage
11636          * @param geometry_shader_code               Source code for geometry shader stage
11637          * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11638          * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11639          * @param vertex_shader_code                 Source code for vertex shader stage
11640          *
11641          * @return true if program was built without errors, false otherwise
11642          **/
11643         bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11644                                                  const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11645                                                  const char* vertex_shader_code)
11646         {
11647                 bool   is_program_built = true;
11648                 GLuint program_id               = 0;
11649
11650                 program_id =
11651                         BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11652                                                  geometry_shader_code, fragment_shader_code, &is_program_built);
11653
11654                 if (0 != program_id)
11655                 {
11656                         glDeleteProgram(program_id);
11657                 }
11658
11659                 return is_program_built;
11660         }
11661 };
11662 }
11663
11664 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11665         : TestCaseGroup(context, "shader_image_load_store", "")
11666 {
11667 }
11668
11669 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11670 {
11671 }
11672
11673 void ShaderImageLoadStoreTests::init()
11674 {
11675         using namespace deqp;
11676         addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11677         addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11678         addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11679         addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11680         addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11681         addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11682         addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11683                                                          TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11684         addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11685                                                          TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11686         addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11687                                                          TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11688         addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11689         addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11690         addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11691         addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11692         addChild(
11693                 new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11694         addChild(
11695                 new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11696         addChild(
11697                 new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11698         addChild(
11699                 new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11700         addChild(
11701                 new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11702         addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11703         addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11704         addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11705         addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11706         addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11707         addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11708         addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11709         addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11710         addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11711         addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11712         addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11713         addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11714         addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11715         addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11716         addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11717                                                          TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11718         addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11719         addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11720         addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11721         addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11722         addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11723         addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11724         addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11725         addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11726         addChild(
11727                 new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11728         addChild(
11729                 new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11730         addChild(
11731                 new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11732         addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11733         addChild(
11734                 new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11735         addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11736         addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11737         addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11738         addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11739         addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11740 }
11741 }