xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cShaderStorageBufferObjectTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cShaderStorageBufferObjectTests.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuMatrix.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include <assert.h>
29 #include <cmath>
30 #include <cstdarg>
31 
32 namespace gl4cts
33 {
34 using namespace glw;
35 
36 namespace
37 {
38 typedef tcu::Vec2 vec2;
39 typedef tcu::Vec3 vec3;
40 typedef tcu::Vec4 vec4;
41 typedef tcu::IVec4 ivec4;
42 typedef tcu::UVec4 uvec4;
43 typedef tcu::Mat4 mat4;
44 
45 enum ShaderStage
46 {
47     vertex,
48     fragment,
49     compute
50 };
51 
52 enum BufferLayout
53 {
54     std140,
55     std430,
56     shared,
57     packed
58 };
59 
60 enum ElementType
61 {
62     vector,
63     matrix_cm,
64     matrix_rm,
65     structure
66 };
67 
68 enum BindingSeq
69 {
70     bindbasebefore,
71     bindbaseafter,
72     bindrangeoffset,
73     bindrangesize
74 };
75 
76 const char *const kGLSLVer = "#version 430 core\n";
77 
78 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
79 {
Title()80     virtual std::string Title()
81     {
82         return "";
83     }
84 
Purpose()85     virtual std::string Purpose()
86     {
87         return "";
88     }
89 
Method()90     virtual std::string Method()
91     {
92         return "";
93     }
94 
PassCriteria()95     virtual std::string PassCriteria()
96     {
97         return "";
98     }
99 
100 public:
SupportedInVS(int requiredVS)101     bool SupportedInVS(int requiredVS)
102     {
103         GLint blocksVS;
104         glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
105         if (blocksVS >= requiredVS)
106             return true;
107         else
108         {
109             std::ostringstream reason;
110             reason << "Required " << requiredVS << " VS storage blocks but only " << blocksVS << " available."
111                    << std::endl;
112             OutputNotSupported(reason.str());
113             return false;
114         }
115     }
116 
SupportedInTCS(int requiredTCS)117     bool SupportedInTCS(int requiredTCS)
118     {
119         GLint blocksTCS;
120         glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &blocksTCS);
121         if (blocksTCS >= requiredTCS)
122             return true;
123         else
124         {
125             std::ostringstream reason;
126             reason << "Required " << requiredTCS << " TCS storage blocks but only " << blocksTCS << " available."
127                    << std::endl;
128             OutputNotSupported(reason.str());
129             return false;
130         }
131     }
132 
SupportedInTES(int requiredTES)133     bool SupportedInTES(int requiredTES)
134     {
135         GLint blocksTES;
136         glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &blocksTES);
137         if (blocksTES >= requiredTES)
138             return true;
139         else
140         {
141             std::ostringstream reason;
142             reason << "Required " << requiredTES << " TES storage blocks but only " << blocksTES << " available."
143                    << std::endl;
144             OutputNotSupported(reason.str());
145             return false;
146         }
147     }
148 
SupportedInGS(int requiredGS)149     bool SupportedInGS(int requiredGS)
150     {
151         GLint blocksGS;
152         glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &blocksGS);
153         if (blocksGS >= requiredGS)
154             return true;
155         else
156         {
157             std::ostringstream reason;
158             reason << "Required " << requiredGS << " GS storage blocks but only " << blocksGS << " available."
159                    << std::endl;
160             OutputNotSupported(reason.str());
161             return false;
162         }
163     }
164 
getWindowWidth()165     int getWindowWidth()
166     {
167         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
168         return renderTarget.getWidth();
169     }
170 
getWindowHeight()171     int getWindowHeight()
172     {
173         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
174         return renderTarget.getHeight();
175     }
176 
ColorEqual(const vec3 & c0,const vec3 & c1,const vec4 & epsilon)177     inline bool ColorEqual(const vec3 &c0, const vec3 &c1, const vec4 &epsilon)
178     {
179         if (fabs(c0[0] - c1[0]) > epsilon[0])
180             return false;
181         if (fabs(c0[1] - c1[1]) > epsilon[1])
182             return false;
183         if (fabs(c0[2] - c1[2]) > epsilon[2])
184             return false;
185         return true;
186     }
187 
CheckProgram(GLuint program)188     bool CheckProgram(GLuint program)
189     {
190         GLint status;
191         glGetProgramiv(program, GL_LINK_STATUS, &status);
192 
193         if (status == GL_FALSE)
194         {
195             GLint attached_shaders;
196             glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
197 
198             if (attached_shaders > 0)
199             {
200                 std::vector<GLuint> shaders(attached_shaders);
201                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
202 
203                 for (GLint i = 0; i < attached_shaders; ++i)
204                 {
205                     GLenum type;
206                     glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
207 
208                     switch (type)
209                     {
210                     case GL_VERTEX_SHADER:
211                         m_context.getTestContext().getLog()
212                             << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
213                         break;
214                     case GL_TESS_CONTROL_SHADER:
215                         m_context.getTestContext().getLog()
216                             << tcu::TestLog::Message << "*** Tessellation Control Shader ***"
217                             << tcu::TestLog::EndMessage;
218                         break;
219                     case GL_TESS_EVALUATION_SHADER:
220                         m_context.getTestContext().getLog()
221                             << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
222                             << tcu::TestLog::EndMessage;
223                         break;
224                     case GL_GEOMETRY_SHADER:
225                         m_context.getTestContext().getLog()
226                             << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
227                         break;
228                     case GL_FRAGMENT_SHADER:
229                         m_context.getTestContext().getLog()
230                             << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
231                         break;
232                     case GL_COMPUTE_SHADER:
233                         m_context.getTestContext().getLog()
234                             << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
235                         break;
236                     default:
237                         m_context.getTestContext().getLog()
238                             << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
239                         break;
240                     }
241 
242                     GLint length;
243                     glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
244                     if (length > 0)
245                     {
246                         std::vector<GLchar> source(length);
247                         glGetShaderSource(shaders[i], length, NULL, &source[0]);
248                         m_context.getTestContext().getLog()
249                             << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
250                     }
251                     glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
252                     if (length > 0)
253                     {
254                         std::vector<GLchar> log(length);
255                         glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
256                         m_context.getTestContext().getLog()
257                             << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
258                     }
259                 }
260             }
261             GLint length;
262             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
263             if (length > 0)
264             {
265                 std::vector<GLchar> log(length);
266                 glGetProgramInfoLog(program, length, NULL, &log[0]);
267                 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
268             }
269         }
270 
271         return status == GL_TRUE ? true : false;
272     }
273 
CreateProgram(const std::string & vs,const std::string & tcs,const std::string & tes,const std::string & gs,const std::string & fs)274     GLuint CreateProgram(const std::string &vs, const std::string &tcs, const std::string &tes, const std::string &gs,
275                          const std::string &fs)
276     {
277         const GLuint p = glCreateProgram();
278         if (!vs.empty())
279         {
280             const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
281             glAttachShader(p, sh);
282             glDeleteShader(sh);
283             const char *const src[2] = {kGLSLVer, vs.c_str()};
284             glShaderSource(sh, 2, src, NULL);
285             glCompileShader(sh);
286         }
287         if (!tcs.empty())
288         {
289             const GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
290             glAttachShader(p, sh);
291             glDeleteShader(sh);
292             const char *const src[2] = {kGLSLVer, tcs.c_str()};
293             glShaderSource(sh, 2, src, NULL);
294             glCompileShader(sh);
295         }
296         if (!tes.empty())
297         {
298             const GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
299             glAttachShader(p, sh);
300             glDeleteShader(sh);
301             const char *const src[2] = {kGLSLVer, tes.c_str()};
302             glShaderSource(sh, 2, src, NULL);
303             glCompileShader(sh);
304         }
305         if (!gs.empty())
306         {
307             const GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
308             glAttachShader(p, sh);
309             glDeleteShader(sh);
310             const char *const src[2] = {kGLSLVer, gs.c_str()};
311             glShaderSource(sh, 2, src, NULL);
312             glCompileShader(sh);
313         }
314         if (!fs.empty())
315         {
316             const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
317             glAttachShader(p, sh);
318             glDeleteShader(sh);
319             const char *const src[2] = {kGLSLVer, fs.c_str()};
320             glShaderSource(sh, 2, src, NULL);
321             glCompileShader(sh);
322         }
323         return p;
324     }
325 
CreateProgram(const std::string & vs,const std::string & fs)326     GLuint CreateProgram(const std::string &vs, const std::string &fs)
327     {
328         const GLuint p = glCreateProgram();
329 
330         if (!vs.empty())
331         {
332             const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
333             glAttachShader(p, sh);
334             glDeleteShader(sh);
335             const char *const src[2] = {kGLSLVer, vs.c_str()};
336             glShaderSource(sh, 2, src, NULL);
337             glCompileShader(sh);
338         }
339         if (!fs.empty())
340         {
341             const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
342             glAttachShader(p, sh);
343             glDeleteShader(sh);
344             const char *const src[2] = {kGLSLVer, fs.c_str()};
345             glShaderSource(sh, 2, src, NULL);
346             glCompileShader(sh);
347         }
348 
349         return p;
350     }
351 
CreateProgramCS(const std::string & cs)352     GLuint CreateProgramCS(const std::string &cs)
353     {
354         const GLuint p = glCreateProgram();
355 
356         if (!cs.empty())
357         {
358             const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
359             glAttachShader(p, sh);
360             glDeleteShader(sh);
361             const char *const src[2] = {kGLSLVer, cs.c_str()};
362             glShaderSource(sh, 2, src, NULL);
363             glCompileShader(sh);
364         }
365         return p;
366     }
367 
BuildShaderProgram(GLenum type,const std::string & source)368     GLuint BuildShaderProgram(GLenum type, const std::string &source)
369     {
370         if (type == GL_COMPUTE_SHADER)
371         {
372             const char *const src[3] = {kGLSLVer, "#extension GL_ARB_compute_shader : require\n", source.c_str()};
373             return glCreateShaderProgramv(type, 3, src);
374         }
375 
376         const char *const src[2] = {kGLSLVer, source.c_str()};
377         return glCreateShaderProgramv(type, 2, src);
378     }
379 
ValidateReadBuffer(int x,int y,int w,int h,const vec3 & expected)380     bool ValidateReadBuffer(int x, int y, int w, int h, const vec3 &expected)
381     {
382         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
383         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
384         vec4 g_color_eps                      = vec4(
385             1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
386             1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
387 
388         std::vector<vec3> display(w * h);
389         glReadPixels(x, y, w, h, GL_RGB, GL_FLOAT, &display[0]);
390 
391         bool result = true;
392         for (int j = 0; j < h; ++j)
393         {
394             for (int i = 0; i < w; ++i)
395             {
396                 if (!ColorEqual(display[j * w + i], expected, g_color_eps))
397                 {
398                     m_context.getTestContext().getLog()
399                         << tcu::TestLog::Message << "Color at (" << x + i << ", " << y + j << ") is ("
400                         << display[j * w + i][0] << " " << display[j * w + i][1] << " " << display[j * w + i][2]
401                         << ") should be (" << expected[0] << " " << expected[1] << " " << expected[2] << ")."
402                         << tcu::TestLog::EndMessage;
403                     result = false;
404                 }
405             }
406         }
407 
408         return result;
409     }
410 
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)411     bool ValidateWindow4Quads(const vec3 &lb, const vec3 &rb, const vec3 &rt, const vec3 &lt, int *bad_pixels = NULL)
412     {
413         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
414         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
415         vec4 g_color_eps                      = vec4(
416             1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
417             1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
418 
419         const int width  = 100;
420         const int height = 100;
421         std::vector<vec3> fb(width * height);
422         glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, &fb[0]);
423 
424         bool status = true;
425         int bad     = 0;
426 
427         // left-bottom quad
428         for (int y = 10; y < height / 2 - 10; ++y)
429         {
430             for (int x = 10; x < width / 2 - 10; ++x)
431             {
432                 const int idx = y * width + x;
433                 if (!ColorEqual(fb[idx], lb, g_color_eps))
434                 {
435                     m_context.getTestContext().getLog()
436                         << tcu::TestLog::Message << "First bad color (" << x << ", " << y << "): " << fb[idx][0] << " "
437                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
438                     status = false;
439                     bad++;
440                 }
441             }
442         }
443         if (!status)
444         {
445             m_context.getTestContext().getLog()
446                 << tcu::TestLog::Message << "Left-bottom quad checking failed. Bad pixels: " << bad
447                 << tcu::TestLog::EndMessage;
448             //return status;
449         }
450         // right-bottom quad
451         for (int y = 10; y < height / 2 - 10; ++y)
452         {
453             for (int x = width / 2 + 10; x < width - 10; ++x)
454             {
455                 const int idx = y * width + x;
456                 if (!ColorEqual(fb[idx], rb, g_color_eps))
457                 {
458                     m_context.getTestContext().getLog()
459                         << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
460                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
461                     status = false;
462                     bad++;
463                 }
464             }
465         }
466         if (!status)
467         {
468             m_context.getTestContext().getLog()
469                 << tcu::TestLog::Message << "right-bottom quad checking failed. Bad pixels: " << bad
470                 << tcu::TestLog::EndMessage;
471             //return status;
472         }
473         // right-top quad
474         for (int y = height / 2 + 10; y < height - 10; ++y)
475         {
476             for (int x = width / 2 + 10; x < width - 10; ++x)
477             {
478                 const int idx = y * width + x;
479                 if (!ColorEqual(fb[idx], rt, g_color_eps))
480                 {
481                     m_context.getTestContext().getLog()
482                         << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
483                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
484                     status = false;
485                     bad++;
486                 }
487             }
488         }
489         if (!status)
490         {
491             m_context.getTestContext().getLog()
492                 << tcu::TestLog::Message << "right-top quad checking failed. Bad pixels: " << bad
493                 << tcu::TestLog::EndMessage;
494             //return status;
495         }
496         // left-top quad
497         for (int y = height / 2 + 10; y < height - 10; ++y)
498         {
499             for (int x = 10; x < width / 2 - 10; ++x)
500             {
501                 const int idx = y * width + x;
502                 if (!ColorEqual(fb[idx], lt, g_color_eps))
503                 {
504                     m_context.getTestContext().getLog()
505                         << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
506                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
507                     status = false;
508                     bad++;
509                 }
510             }
511         }
512         if (!status)
513         {
514             m_context.getTestContext().getLog()
515                 << tcu::TestLog::Message << "left-top quad checking failed. Bad pixels: " << bad
516                 << tcu::TestLog::EndMessage;
517             //return status;
518         }
519         // middle horizontal line should be black
520         for (int y = height / 2 - 2; y < height / 2 + 2; ++y)
521         {
522             for (int x = 0; x < width; ++x)
523             {
524                 const int idx = y * width + x;
525                 if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
526                 {
527                     m_context.getTestContext().getLog()
528                         << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
529                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
530                     status = false;
531                     bad++;
532                 }
533             }
534         }
535         if (!status)
536         {
537             m_context.getTestContext().getLog()
538                 << tcu::TestLog::Message << "middle horizontal line checking failed. Bad pixels: " << bad
539                 << tcu::TestLog::EndMessage;
540             //return status;
541         }
542         // middle vertical line should be black
543         for (int y = 0; y < height; ++y)
544         {
545             for (int x = width / 2 - 2; x < width / 2 + 2; ++x)
546             {
547                 const int idx = y * width + x;
548                 if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
549                 {
550                     m_context.getTestContext().getLog()
551                         << tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
552                         << fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
553                     status = false;
554                     bad++;
555                 }
556             }
557         }
558         if (!status)
559         {
560             m_context.getTestContext().getLog()
561                 << tcu::TestLog::Message << "middle vertical line checking failed. Bad pixels: " << bad
562                 << tcu::TestLog::EndMessage;
563             //return status;
564         }
565 
566         if (bad_pixels)
567             *bad_pixels = bad;
568         m_context.getTestContext().getLog()
569             << tcu::TestLog::Message << "Bad pixels: " << (bad_pixels == NULL ? 0 : *bad_pixels)
570             << ", counted bad: " << bad << tcu::TestLog::EndMessage;
571         return status;
572     }
573 
Translation(float tx,float ty,float tz)574     const mat4 Translation(float tx, float ty, float tz)
575     {
576         float d[] = {1.0f, 0.0f, 0.0f, tx, 0.0f, 1.0f, 0.0f, ty, 0.0f, 0.0f, 1.0f, tz, 0.0f, 0.0f, 0.0f, 1.0f};
577         return mat4(d);
578     }
579 
GLenumToString(GLenum e)580     const char *GLenumToString(GLenum e)
581     {
582         switch (e)
583         {
584         case GL_SHADER_STORAGE_BUFFER_BINDING:
585             return "GL_SHADER_STORAGE_BUFFER_BINDING";
586         case GL_SHADER_STORAGE_BUFFER_START:
587             return "GL_SHADER_STORAGE_BUFFER_START";
588         case GL_SHADER_STORAGE_BUFFER_SIZE:
589             return "GL_SHADER_STORAGE_BUFFER_SIZE";
590         case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
591             return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
592         case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
593             return "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS";
594         case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS:
595             return "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS";
596         case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS:
597             return "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS";
598         case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
599             return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
600         case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
601             return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
602         case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
603             return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
604         case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
605             return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
606         case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
607             return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
608         case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
609             return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
610         case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
611             return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
612 
613         default:
614             assert(0);
615             break;
616         }
617         return NULL;
618     }
619 };
620 
621 //-----------------------------------------------------------------------------
622 // 1.1 BasicBasic
623 //-----------------------------------------------------------------------------
624 
625 class BasicBasic : public ShaderStorageBufferObjectBase
626 {
627     GLuint m_program;
628     GLuint m_buffer;
629     GLuint m_vertex_array;
630 
RunIteration(GLuint index)631     bool RunIteration(GLuint index)
632     {
633         glClear(GL_COLOR_BUFFER_BIT);
634         glShaderStorageBlockBinding(m_program, 0, index);
635         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, m_buffer);
636         glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
637         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, 0);
638 
639         return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
640     }
641 
Setup()642     virtual long Setup()
643     {
644         m_program      = 0;
645         m_buffer       = 0;
646         m_vertex_array = 0;
647         return NO_ERROR;
648     }
649 
Run()650     virtual long Run()
651     {
652         if (!SupportedInVS(1))
653             return NOT_SUPPORTED;
654 
655         const char *const glsl_vs =
656             NL "layout(std430, binding = 1) buffer InputBuffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL
657                "void main() {" NL "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}";
658 
659         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
660                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
661 
662         m_program = CreateProgram(glsl_vs, glsl_fs);
663         glLinkProgram(m_program);
664         if (!CheckProgram(m_program))
665             return ERROR;
666 
667         const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
668         glGenBuffers(1, &m_buffer);
669         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
670         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
671         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
672 
673         glGenVertexArrays(1, &m_vertex_array);
674         glBindVertexArray(m_vertex_array);
675 
676         glUseProgram(m_program);
677 
678         for (GLuint i = 0; i < 8; ++i)
679         {
680             if (!RunIteration(i))
681                 return ERROR;
682         }
683         return NO_ERROR;
684     }
685 
Cleanup()686     virtual long Cleanup()
687     {
688         glUseProgram(0);
689         glDeleteProgram(m_program);
690         glDeleteBuffers(1, &m_buffer);
691         glDeleteVertexArrays(1, &m_vertex_array);
692         return NO_ERROR;
693     }
694 };
695 
696 class BasicBasicCS : public ShaderStorageBufferObjectBase
697 {
698     GLuint m_program;
699     GLuint m_buffer;
700 
Setup()701     virtual long Setup()
702     {
703         m_program = 0;
704         m_buffer  = 0;
705         return NO_ERROR;
706     }
707 
Run()708     virtual long Run()
709     {
710         const char *const glsl_cs = NL "layout(local_size_x = 1) in;" NL "buffer Buffer {" NL "  int result;" NL "};" NL
711                                        "void main() {" NL "  result = 7;" NL "}";
712         m_program = CreateProgramCS(glsl_cs);
713         glLinkProgram(m_program);
714         if (!CheckProgram(m_program))
715             return ERROR;
716 
717         glGenBuffers(1, &m_buffer);
718         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
719         glBufferData(GL_SHADER_STORAGE_BUFFER, 4, 0, GL_STATIC_READ);
720         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
721 
722         glUseProgram(m_program);
723         glDispatchCompute(1, 1, 1);
724         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
725 
726         GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
727         if (!out_data)
728             return ERROR;
729         if (*out_data == 7)
730             return NO_ERROR;
731         else
732             return ERROR;
733     }
734 
Cleanup()735     virtual long Cleanup()
736     {
737         glUseProgram(0);
738         glDeleteProgram(m_program);
739         glDeleteBuffers(1, &m_buffer);
740         return NO_ERROR;
741     }
742 };
743 //-----------------------------------------------------------------------------
744 // 1.2 BasicMax
745 //-----------------------------------------------------------------------------
746 
747 class BasicMax : public ShaderStorageBufferObjectBase
748 {
Check(GLenum e,GLint64 value,bool max_value)749     bool Check(GLenum e, GLint64 value, bool max_value)
750     {
751         GLint i;
752         GLint64 i64;
753         GLfloat f;
754         GLdouble d;
755         GLboolean b;
756 
757         glGetIntegerv(e, &i);
758         glGetInteger64v(e, &i64);
759         glGetFloatv(e, &f);
760         glGetDoublev(e, &d);
761         glGetBooleanv(e, &b);
762 
763         bool status = true;
764         if (max_value)
765         {
766             if (static_cast<GLint64>(i) < value)
767                 status = false;
768             if (i64 < value)
769                 status = false;
770             if (static_cast<GLint64>(f) < value)
771                 status = false;
772             if (static_cast<GLint64>(d) < value)
773                 status = false;
774 
775             if (!status)
776             {
777                 m_context.getTestContext().getLog()
778                     << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at least "
779                     << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
780             }
781         }
782         else
783         {
784             if (static_cast<GLint64>(i) > value)
785                 status = false;
786             if (i64 > value)
787                 status = false;
788             if (static_cast<GLint64>(f) > value)
789                 status = false;
790             if (static_cast<GLint64>(d) > value)
791                 status = false;
792 
793             if (!status)
794             {
795                 m_context.getTestContext().getLog()
796                     << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at most "
797                     << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
798             }
799         }
800         return status;
801     }
802 
Run()803     virtual long Run()
804     {
805         if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
806             return ERROR;
807         if (!Check(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, 0, true))
808             return ERROR;
809         if (!Check(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, 0, true))
810             return ERROR;
811         if (!Check(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 0, true))
812             return ERROR;
813         if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 8, true))
814             return ERROR;
815         if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 8, true))
816             return ERROR;
817         if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 8, true))
818             return ERROR;
819         if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 16777216 /* 2^24 */, true))
820             return ERROR;
821         if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 8, true))
822             return ERROR;
823         if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8, true))
824             return ERROR;
825         if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
826             return ERROR;
827         return NO_ERROR;
828     }
829 };
830 //-----------------------------------------------------------------------------
831 // 1.3 BasicBinding
832 //-----------------------------------------------------------------------------
833 
834 class BasicBinding : public ShaderStorageBufferObjectBase
835 {
836     GLuint m_buffer[4];
837 
Check(GLenum e,GLuint expected)838     bool Check(GLenum e, GLuint expected)
839     {
840         GLint i;
841         GLint64 i64;
842         GLfloat f;
843         GLdouble d;
844         GLboolean b;
845 
846         glGetIntegerv(e, &i);
847         glGetInteger64v(e, &i64);
848         glGetFloatv(e, &f);
849         glGetDoublev(e, &d);
850         glGetBooleanv(e, &b);
851 
852         bool status = true;
853         if (static_cast<GLuint>(i) != expected)
854             status = false;
855         if (static_cast<GLuint>(i64) != expected)
856             status = false;
857         if (static_cast<GLuint>(f) != expected)
858             status = false;
859         if (static_cast<GLuint>(d) != expected)
860             status = false;
861         if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
862             status = false;
863 
864         if (!status)
865         {
866             m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " is " << i
867                                                 << " should be " << expected << tcu::TestLog::EndMessage;
868         }
869         return status;
870     }
871 
CheckIndexed(GLenum e,GLuint index,GLuint expected)872     bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
873     {
874         GLint i;
875         GLint64 i64;
876         GLfloat f;
877         GLdouble d;
878         GLboolean b;
879 
880         glGetIntegeri_v(e, index, &i);
881         glGetInteger64i_v(e, index, &i64);
882         glGetFloati_v(e, index, &f);
883         glGetDoublei_v(e, index, &d);
884         glGetBooleani_v(e, index, &b);
885 
886         bool status = true;
887         if (static_cast<GLuint>(i) != expected)
888             status = false;
889         if (static_cast<GLuint>(i64) != expected)
890             status = false;
891         if (static_cast<GLuint>(f) != expected)
892             status = false;
893         if (static_cast<GLuint>(d) != expected)
894             status = false;
895         if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
896             status = false;
897 
898         if (!status)
899         {
900             m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " at index " << index
901                                                 << " is " << i << " should be " << expected << tcu::TestLog::EndMessage;
902         }
903         return status;
904     }
905 
Setup()906     virtual long Setup()
907     {
908         memset(m_buffer, 0, sizeof(m_buffer));
909         return NO_ERROR;
910     }
911 
Run()912     virtual long Run()
913     {
914         // check default state
915         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
916             return ERROR;
917         for (GLuint i = 0; i < 8; ++i)
918         {
919             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
920                 return ERROR;
921             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
922                 return ERROR;
923             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
924                 return ERROR;
925         }
926 
927         glGenBuffers(4, m_buffer);
928         for (GLuint i = 0; i < 8; ++i)
929         {
930             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
931 
932             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
933                 return ERROR;
934             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
935                 return ERROR;
936             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
937                 return ERROR;
938             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
939                 return ERROR;
940 
941             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
942 
943             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
944                 return ERROR;
945             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
946                 return ERROR;
947             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
948                 return ERROR;
949             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
950                 return ERROR;
951         }
952 
953         for (GLuint i = 0; i < 8; ++i)
954         {
955             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
956 
957             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
958                 return ERROR;
959             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
960                 return ERROR;
961             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
962                 return ERROR;
963             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
964                 return ERROR;
965 
966             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
967 
968             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
969                 return ERROR;
970             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
971                 return ERROR;
972             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
973                 return ERROR;
974             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
975                 return ERROR;
976 
977             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
978 
979             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
980                 return ERROR;
981             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
982                 return ERROR;
983             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
984                 return ERROR;
985             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
986                 return ERROR;
987         }
988 
989         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
990         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
991             return ERROR;
992         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
993             return ERROR;
994         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
995             return ERROR;
996         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
997             return ERROR;
998 
999         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
1000         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
1001             return ERROR;
1002         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
1003             return ERROR;
1004         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
1005             return ERROR;
1006         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
1007             return ERROR;
1008 
1009         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
1010         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
1011             return ERROR;
1012         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
1013             return ERROR;
1014         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
1015             return ERROR;
1016         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
1017             return ERROR;
1018 
1019         glDeleteBuffers(4, m_buffer);
1020         memset(m_buffer, 0, sizeof(m_buffer));
1021 
1022         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
1023             return ERROR;
1024         for (GLuint i = 0; i < 8; ++i)
1025         {
1026             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
1027                 return ERROR;
1028         }
1029 
1030         return NO_ERROR;
1031     }
1032 
Cleanup()1033     virtual long Cleanup()
1034     {
1035         glDeleteBuffers(4, m_buffer);
1036         return NO_ERROR;
1037     }
1038 };
1039 //-----------------------------------------------------------------------------
1040 // 1.4 BasicSyntax
1041 //-----------------------------------------------------------------------------
1042 
1043 class BasicSyntax : public ShaderStorageBufferObjectBase
1044 {
1045     GLuint m_program;
1046     GLuint m_buffer;
1047     GLuint m_vertex_array;
1048 
RunIteration(const char * vs,const char * fs)1049     bool RunIteration(const char *vs, const char *fs)
1050     {
1051         if (m_program != 0)
1052             glDeleteProgram(m_program);
1053         m_program = CreateProgram(vs, fs);
1054         glLinkProgram(m_program);
1055         if (!CheckProgram(m_program))
1056             return false;
1057 
1058         glClear(GL_COLOR_BUFFER_BIT);
1059         glUseProgram(m_program);
1060         glDrawArrays(GL_TRIANGLES, 0, 3);
1061 
1062         return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1063     }
1064 
Setup()1065     virtual long Setup()
1066     {
1067         m_program      = 0;
1068         m_buffer       = 0;
1069         m_vertex_array = 0;
1070         return NO_ERROR;
1071     }
1072 
Run()1073     virtual long Run()
1074     {
1075         if (!SupportedInVS(1))
1076             return NOT_SUPPORTED;
1077 
1078         const int kCount                  = 8;
1079         const char *const glsl_vs[kCount] = {
1080             NL "layout(std430) buffer Buffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1081                "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1082             NL "coherent buffer Buffer {" NL "  buffer vec4 position0;" NL "  coherent vec4 position1;" NL
1083                "  restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
1084                "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1085                "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1086                "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1087             NL "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
1088                "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
1089             NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1090                "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1091                "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1092                "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1093             NL "buffer Buffer {" NL "  vec4 position[3];" NL "} g_buffer[1];" NL "void main() {" NL
1094                "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1095             NL "layout(shared) coherent buffer Buffer {" NL "  restrict volatile vec4 position0;" NL
1096                "  buffer readonly vec4 position1;" NL "  vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
1097                "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1098                "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1099                "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1100             NL "layout(packed) coherent buffer Buffer {" NL "  vec4 position01[];" NL "  vec4 position2;" NL
1101                "} g_buffer;" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1102                "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1103                "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1104             NL "layout(std430) coherent buffer Buffer {" NL "  coherent vec4 position01[];" NL "  vec4 position2[];" NL
1105                "} g_buffer;" NL "void main() {" NL "  switch (gl_VertexID) {" NL
1106                "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
1107                "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
1108                "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
1109         };
1110         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1111                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1112 
1113         // full viewport triangle
1114         const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
1115         glGenBuffers(1, &m_buffer);
1116         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1117         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1118 
1119         glGenVertexArrays(1, &m_vertex_array);
1120         glBindVertexArray(m_vertex_array);
1121 
1122         for (int i = 0; i < kCount; ++i)
1123         {
1124             if (!RunIteration(glsl_vs[i], glsl_fs))
1125                 return ERROR;
1126         }
1127 
1128         return NO_ERROR;
1129     }
1130 
Cleanup()1131     virtual long Cleanup()
1132     {
1133         glUseProgram(0);
1134         glDeleteProgram(m_program);
1135         glDeleteBuffers(1, &m_buffer);
1136         glDeleteVertexArrays(1, &m_vertex_array);
1137         return NO_ERROR;
1138     }
1139 };
1140 //-----------------------------------------------------------------------------
1141 // 1.5 BasicSyntaxSSO
1142 //-----------------------------------------------------------------------------
1143 
1144 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1145 {
1146     GLuint m_pipeline;
1147     GLuint m_vsp, m_fsp;
1148     GLuint m_buffer;
1149     GLuint m_vertex_array;
1150 
RunIteration(const char * vs)1151     bool RunIteration(const char *vs)
1152     {
1153         if (m_vsp != 0)
1154             glDeleteProgram(m_vsp);
1155         m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1156         if (!CheckProgram(m_vsp))
1157             return false;
1158 
1159         glClear(GL_COLOR_BUFFER_BIT);
1160         glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1161         glDrawArrays(GL_TRIANGLES, 0, 3);
1162 
1163         return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1164     }
1165 
Setup()1166     virtual long Setup()
1167     {
1168         m_pipeline = 0;
1169         m_vsp = m_fsp  = 0;
1170         m_buffer       = 0;
1171         m_vertex_array = 0;
1172         return NO_ERROR;
1173     }
1174 
Run()1175     virtual long Run()
1176     {
1177         if (!SupportedInVS(1))
1178             return NOT_SUPPORTED;
1179         const int kCount                  = 8;
1180         const char *const glsl_vs[kCount] = {
1181             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std430) buffer Buffer {" NL
1182                "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1183                "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1184             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "coherent buffer Buffer {" NL
1185                "  vec4 position0;" NL "  coherent vec4 position1;" NL "  restrict readonly vec4 position2;" NL
1186                "} g_input_buffer;" NL "void main() {" NL
1187                "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1188                "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1189                "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1190             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL
1191                "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
1192                "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
1193             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL
1194                "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1195                "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1196                "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1197                "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1198             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "buffer Buffer {" NL "  vec4 position[3];" NL
1199                "} g_buffer[1];" NL "void main() {" NL "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1200             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(shared) coherent buffer Buffer {" NL
1201                "  restrict volatile vec4 position0;" NL "  readonly vec4 position1;" NL "  vec4 position2;" NL
1202                "} g_buffer[1];" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1203                "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1204                "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1205             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(packed) coherent buffer Buffer {" NL
1206                "  vec4 position01[];" NL "  vec4 position2;" NL "} g_buffer;" NL "void main() {" NL
1207                "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1208                "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1209                "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1210             NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL
1211                "  coherent vec4 position01[];" NL "  vec4 position2[];" NL "} g_buffer;" NL "void main() {" NL
1212                "  switch (gl_VertexID) {" NL "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
1213                "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
1214                "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
1215         };
1216         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1217                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1218         m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
1219         if (!CheckProgram(m_fsp))
1220             return ERROR;
1221 
1222         glGenProgramPipelines(1, &m_pipeline);
1223         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
1224 
1225         // full viewport triangle
1226         const float data[12] = {-1.0f, -1.0f, 0.0f, 1.0f, 3.0f, -1.0f, 0.0f, 1.0f, -1.0f, 3.0f, 0.0f, 1.0f};
1227         glGenBuffers(1, &m_buffer);
1228         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1229         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1230 
1231         glBindProgramPipeline(m_pipeline);
1232 
1233         glGenVertexArrays(1, &m_vertex_array);
1234         glBindVertexArray(m_vertex_array);
1235 
1236         for (int i = 0; i < kCount; ++i)
1237         {
1238             if (!RunIteration(glsl_vs[i]))
1239                 return ERROR;
1240         }
1241 
1242         return NO_ERROR;
1243     }
1244 
Cleanup()1245     virtual long Cleanup()
1246     {
1247         glDeleteProgramPipelines(1, &m_pipeline);
1248         glDeleteProgram(m_vsp);
1249         glDeleteProgram(m_fsp);
1250         glDeleteBuffers(1, &m_buffer);
1251         glDeleteVertexArrays(1, &m_vertex_array);
1252         return NO_ERROR;
1253     }
1254 };
1255 //-----------------------------------------------------------------------------
1256 // 1.6.x BasicStdLayoutBase
1257 //-----------------------------------------------------------------------------
1258 
1259 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1260 {
1261     GLuint m_program;
1262     GLuint m_buffer[2];
1263     GLuint m_vertex_array;
1264 
1265     virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1266 
Setup()1267     virtual long Setup()
1268     {
1269         m_program = 0;
1270         memset(m_buffer, 0, sizeof(m_buffer));
1271         m_vertex_array = 0;
1272         return NO_ERROR;
1273     }
1274 
Run()1275     virtual long Run()
1276     {
1277         if (!SupportedInVS(2))
1278             return NOT_SUPPORTED;
1279         std::vector<GLubyte> in_data;
1280         const char *glsl_vs = GetInput(in_data);
1281 
1282         m_program = CreateProgram(glsl_vs, "");
1283         glLinkProgram(m_program);
1284         if (!CheckProgram(m_program))
1285             return ERROR;
1286 
1287         glGenBuffers(2, m_buffer);
1288 
1289         // output buffer
1290         std::vector<GLubyte> out_data(in_data.size());
1291         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1292         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &out_data[0], GL_STATIC_DRAW);
1293 
1294         // input buffer
1295         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1296         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1297 
1298         glGenVertexArrays(1, &m_vertex_array);
1299         glEnable(GL_RASTERIZER_DISCARD);
1300 
1301         glUseProgram(m_program);
1302         glBindVertexArray(m_vertex_array);
1303         glDrawArrays(GL_POINTS, 0, 1);
1304 
1305         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1306         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1307         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), &out_data[0]);
1308 
1309         bool status = true;
1310         for (size_t i = 0; i < in_data.size(); ++i)
1311         {
1312             if (in_data[i] != out_data[i])
1313             {
1314                 m_context.getTestContext().getLog()
1315                     << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1316                     << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1317                 status = false;
1318             }
1319         }
1320         if (!status)
1321             return ERROR;
1322         return NO_ERROR;
1323     }
1324 
Cleanup()1325     virtual long Cleanup()
1326     {
1327         glDisable(GL_RASTERIZER_DISCARD);
1328         glUseProgram(0);
1329         glDeleteProgram(m_program);
1330         glDeleteBuffers(2, m_buffer);
1331         glDeleteVertexArrays(1, &m_vertex_array);
1332         return NO_ERROR;
1333     }
1334 };
1335 
1336 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1337 {
1338     GLuint m_program;
1339     GLuint m_buffer[2];
1340 
1341     virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1342 
Setup()1343     virtual long Setup()
1344     {
1345         m_program = 0;
1346         memset(m_buffer, 0, sizeof(m_buffer));
1347         return NO_ERROR;
1348     }
1349 
Run()1350     virtual long Run()
1351     {
1352         std::vector<GLubyte> in_data;
1353         std::stringstream ss;
1354         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1355 
1356         m_program = CreateProgramCS(ss.str());
1357         glLinkProgram(m_program);
1358         if (!CheckProgram(m_program))
1359             return ERROR;
1360 
1361         glGenBuffers(2, m_buffer);
1362 
1363         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1364         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1365         std::vector<GLubyte> out_d(in_data.size());
1366         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1367         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)out_d.size(), &out_d[0], GL_STATIC_DRAW);
1368 
1369         glUseProgram(m_program);
1370         glDispatchCompute(1, 1, 1);
1371 
1372         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1373         GLubyte *out_data =
1374             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1375         if (!out_data)
1376             return ERROR;
1377 
1378         bool status = true;
1379 
1380         for (size_t i = 0; i < in_data.size(); ++i)
1381         {
1382             if (in_data[i] != out_data[i])
1383             {
1384                 m_context.getTestContext().getLog()
1385                     << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1386                     << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1387                 status = false;
1388             }
1389         }
1390         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1391         if (!status)
1392             return ERROR;
1393         return NO_ERROR;
1394     }
1395 
Cleanup()1396     virtual long Cleanup()
1397     {
1398         glUseProgram(0);
1399         glDeleteProgram(m_program);
1400         glDeleteBuffers(2, m_buffer);
1401         return NO_ERROR;
1402     }
1403 };
1404 //-----------------------------------------------------------------------------
1405 // 1.6.1 BasicStd430LayoutCase1
1406 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1407 const char *GetInput430c1(std::vector<GLubyte> &in_data)
1408 {
1409     in_data.resize(6 * 4);
1410     float *fp = reinterpret_cast<float *>(&in_data[0]);
1411     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1412     fp[0]     = 1.0f;
1413     fp[1]     = 2.0f;
1414     fp[2]     = 3.0f;
1415     fp[3]     = 4.0f;
1416     ip[4]     = 5;
1417     ip[5]     = 6;
1418 
1419     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1420               "  ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL
1421               "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1422               "  g_output.data0 = g_input.data0;" NL
1423               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1424               "  g_output.data2 = g_input.data2;" NL "}";
1425 }
1426 
1427 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1428 {
GetInput(std::vector<GLubyte> & in_data)1429     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1430     {
1431         return GetInput430c1(in_data);
1432     }
1433 };
1434 
1435 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1436 {
GetInput(std::vector<GLubyte> & in_data)1437     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1438     {
1439         return GetInput430c1(in_data);
1440     }
1441 };
1442 //-----------------------------------------------------------------------------
1443 // 1.6.2 BasicStd430LayoutCase2
1444 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1445 const char *GetInput430c2(std::vector<GLubyte> &in_data)
1446 {
1447     in_data.resize(20 * 4);
1448     float *fp = reinterpret_cast<float *>(&in_data[0]);
1449     fp[0]     = 1.0f;
1450     fp[1]     = 2.0f;
1451     fp[2]     = 3.0f;
1452     fp[3]     = 4.0f;
1453     fp[4]     = 5.0f;
1454     fp[5]     = 6.0f;
1455     fp[8]     = 7.0f;
1456     fp[9]     = 8.0f;
1457     fp[10]    = 9.0f;
1458     fp[12]    = 10.0f;
1459     fp[13]    = 11.0f;
1460     fp[14]    = 12.0f;
1461     fp[16]    = 13.0f;
1462 
1463     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1464               "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1465               "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1466               "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1467               "  g_output.data0 = g_input.data0;" NL
1468               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1469               "  g_output.data2 = g_input.data2;" NL
1470               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1471               "  g_output.data4 = g_input.data4;" NL "}";
1472 }
1473 
1474 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1475 {
GetInput(std::vector<GLubyte> & in_data)1476     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1477     {
1478         return GetInput430c2(in_data);
1479     }
1480 };
1481 
1482 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1483 {
GetInput(std::vector<GLubyte> & in_data)1484     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1485     {
1486         return GetInput430c2(in_data);
1487     }
1488 };
1489 
1490 //-----------------------------------------------------------------------------
1491 // 1.6.3 BasicStd430LayoutCase3
1492 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1493 const char *GetInput430c3(std::vector<GLubyte> &in_data)
1494 {
1495     in_data.resize(16 * 4);
1496     float *fp = reinterpret_cast<float *>(&in_data[0]);
1497     fp[0]     = 1.0f;
1498     fp[1]     = 2.0f;
1499     fp[2]     = 3.0f;
1500     fp[3]     = 0.0f;
1501     fp[4]     = 4.0f;
1502     fp[5]     = 5.0f;
1503     fp[6]     = 6.0f;
1504     fp[7]     = 0.0f;
1505     fp[8]     = 7.0f;
1506     fp[9]     = 8.0f;
1507     fp[10]    = 9.0f;
1508     fp[11]    = 10.0f;
1509     fp[12]    = 11.0f;
1510     fp[13]    = 12.0f;
1511     fp[14]    = 13.0f;
1512     fp[15]    = 14.0f;
1513 
1514     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat2x3 data0;" NL
1515               "  layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1516               "  layout(column_major) mat2x3 data0;" NL "  layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1517               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL "}";
1518 }
1519 
1520 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1521 {
GetInput(std::vector<GLubyte> & in_data)1522     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1523     {
1524         return GetInput430c3(in_data);
1525     }
1526 };
1527 
1528 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1529 {
GetInput(std::vector<GLubyte> & in_data)1530     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1531     {
1532         return GetInput430c3(in_data);
1533     }
1534 };
1535 
1536 //-----------------------------------------------------------------------------
1537 // 1.6.4 BasicStd430LayoutCase4
1538 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1539 const char *GetInput430c4(std::vector<GLubyte> &in_data)
1540 {
1541     in_data.resize(20 * 4);
1542     float *fp = reinterpret_cast<float *>(&in_data[0]);
1543     fp[0]     = 1.0f;
1544     fp[1]     = 2.0f;
1545     fp[2]     = 3.0f;
1546     fp[3]     = 4.0f;
1547     fp[4]     = 5.0f;
1548     fp[5]     = 6.0f;
1549     fp[6]     = 7.0f;
1550     fp[7]     = 8.0f;
1551     fp[8]     = 9.0f;
1552     fp[9]     = 10.0f;
1553     fp[10]    = 11.0f;
1554     fp[12]    = 12.0f;
1555     fp[13]    = 13.0f;
1556     fp[14]    = 14.0f;
1557     fp[16]    = 15.0f;
1558 
1559     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1560               "  float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1561               "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1562               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1563               "  g_output.data2 = g_input.data2;" NL "}";
1564 }
1565 
1566 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1567 {
GetInput(std::vector<GLubyte> & in_data)1568     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1569     {
1570         return GetInput430c4(in_data);
1571     }
1572 };
1573 
1574 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1575 {
GetInput(std::vector<GLubyte> & in_data)1576     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1577     {
1578         return GetInput430c4(in_data);
1579     }
1580 };
1581 
1582 //-----------------------------------------------------------------------------
1583 // 1.6.5 BasicStd430LayoutCase5
1584 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1585 const char *GetInput430c5(std::vector<GLubyte> &in_data)
1586 {
1587     in_data.resize(8 * 4);
1588     float *fp = reinterpret_cast<float *>(&in_data[0]);
1589     fp[0]     = 1.0f;
1590     fp[1]     = 3.0f;
1591     fp[2]     = 5.0f;
1592     fp[3]     = 7.0f;
1593     fp[4]     = 2.0f;
1594     fp[5]     = 4.0f;
1595     fp[6]     = 6.0f;
1596     fp[7]     = 8.0f;
1597 
1598     return NL "layout(std430, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1599               "layout(std430, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1600               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1601 }
1602 
1603 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1604 {
GetInput(std::vector<GLubyte> & in_data)1605     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1606     {
1607         return GetInput430c5(in_data);
1608     }
1609 };
1610 
1611 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1612 {
GetInput(std::vector<GLubyte> & in_data)1613     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1614     {
1615         return GetInput430c5(in_data);
1616     }
1617 };
1618 
1619 //-----------------------------------------------------------------------------
1620 // 1.6.6 BasicStd430LayoutCase6
1621 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1622 const char *GetInput430c6(std::vector<GLubyte> &in_data)
1623 {
1624     in_data.resize(92 * 4);
1625     float *fp = reinterpret_cast<float *>(&in_data[0]);
1626     fp[0]     = 1.0f;
1627     fp[1]     = 2.0f;
1628     fp[2]     = 3.0f;
1629     fp[3]     = 4.0f;
1630     fp[4]     = 5.0f;
1631     fp[5]     = 0.0f;
1632     fp[6]     = 6.0f;
1633     fp[7]     = 7.0f;
1634     fp[8]     = 8.0f;
1635     fp[9]     = 9.0f;
1636     fp[10]    = 10.0f;
1637     fp[11]    = 11.0f;
1638     fp[12]    = 12.0f;
1639     fp[13]    = 0.0f;
1640     fp[14]    = 0.0f;
1641     fp[15]    = 0.0f;
1642     fp[16]    = 13.0f;
1643     fp[17]    = 14.0f;
1644     fp[18]    = 15.0f;
1645     fp[19]    = 0.0f;
1646     fp[20]    = 16.0f;
1647     fp[21]    = 17.0f;
1648     fp[22]    = 18.0f;
1649     fp[23]    = 0.0f;
1650     fp[24]    = 19.0f;
1651     fp[25]    = 20.0f;
1652     fp[26]    = 21.0f;
1653     fp[27]    = 22.0f;
1654     fp[28]    = 23.0f;
1655     fp[29]    = 24.0f;
1656     fp[30]    = 25.0f;
1657     fp[31]    = 26.0f;
1658     fp[32]    = 27.0f;
1659     fp[33]    = 28.0f;
1660     fp[34]    = 0.0f;
1661     fp[35]    = 0.0f;
1662     fp[36]    = 29.0f;
1663     fp[37]    = 30.0f;
1664     fp[38]    = 31.0f;
1665     fp[39]    = 0.0f;
1666     fp[40]    = 32.0f;
1667     fp[41]    = 33.0f;
1668     fp[42]    = 34.0f;
1669     fp[43]    = 0.0f;
1670     fp[44]    = 35.0f;
1671     fp[45]    = 36.0f;
1672     fp[46]    = 37.0f;
1673     fp[47]    = 0.0f;
1674     fp[48]    = 38.0f;
1675     fp[49]    = 39.0f;
1676     fp[50]    = 40.0f;
1677     fp[51]    = 0.0f;
1678     fp[52]    = 41.0f;
1679     fp[53]    = 42.0f;
1680     fp[54]    = 43.0f;
1681     fp[55]    = 0.0f;
1682     fp[56]    = 44.0f;
1683     fp[57]    = 45.0f;
1684     fp[58]    = 46.0f;
1685     fp[59]    = 0.0f;
1686     fp[60]    = 47.0f;
1687     fp[61]    = 48.0f;
1688     fp[62]    = 49.0f;
1689     fp[63]    = 50.0f;
1690     fp[64]    = 51.0f;
1691     fp[65]    = 52.0f;
1692     fp[66]    = 53.0f;
1693     fp[67]    = 54.0f;
1694     fp[68]    = 55.0f;
1695     fp[69]    = 56.0f;
1696     fp[70]    = 57.0f;
1697     fp[71]    = 58.0f;
1698     fp[72]    = 59.0f;
1699     fp[73]    = 60.0f;
1700     fp[74]    = 61.0f;
1701     fp[75]    = 62.0f;
1702     fp[76]    = 63.0f;
1703     fp[77]    = 64.0f;
1704     fp[78]    = 65.0f;
1705     fp[79]    = 66.0f;
1706     fp[80]    = 67.0f;
1707     fp[81]    = 68.0f;
1708     fp[82]    = 69.0f;
1709     fp[83]    = 70.0f;
1710     fp[84]    = 71.0f;
1711     fp[85]    = 72.0f;
1712     fp[86]    = 73.0f;
1713     fp[87]    = 74.0f;
1714     fp[88]    = 75.0f;
1715     fp[89]    = 76.0f;
1716     fp[90]    = 77.0f;
1717     fp[91]    = 78.0f;
1718 
1719     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
1720               "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1721               "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_input;" NL
1722               "layout(std430, binding = 1) buffer Output {" NL "  float data0[2];" NL "  float data1[3];" NL
1723               "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1724               "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1725               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1726               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1727               "  g_output.data2 = g_input.data2;" NL
1728               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1729               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1730               "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1731               "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1732               "  for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1733               "  for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1734 }
1735 
1736 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1737 {
GetInput(std::vector<GLubyte> & in_data)1738     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1739     {
1740         return GetInput430c6(in_data);
1741     }
1742 };
1743 
1744 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1745 {
GetInput(std::vector<GLubyte> & in_data)1746     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1747     {
1748         return GetInput430c6(in_data);
1749     }
1750 };
1751 
1752 //-----------------------------------------------------------------------------
1753 // 1.6.7 BasicStd430LayoutCase7
1754 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1755 const char *GetInput430c7(std::vector<GLubyte> &in_data)
1756 {
1757     in_data.resize(36 * 4);
1758     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1759     float *fp = reinterpret_cast<float *>(&in_data[0]);
1760     ip[0]     = 1;
1761     ip[1]     = 0;
1762     ip[2]     = 2;
1763     ip[3]     = 3;
1764     fp[4]     = 4.0f;
1765     fp[5]     = 0.0f;
1766     fp[6]     = 0.0f;
1767     fp[7]     = 0.0f;
1768     fp[8]     = 5.0f;
1769     fp[9]     = 6.0f;
1770     fp[10]    = 7.0f;
1771     fp[11]    = 0.0f;
1772     fp[12]    = 8.0f;
1773     fp[13]    = 0.0f;
1774     fp[14]    = 0.0f;
1775     fp[15]    = 0.0f;
1776     fp[16]    = 9.0f;
1777     fp[17]    = 10.0f;
1778     fp[18]    = 11.0f;
1779     fp[19]    = 0.0f;
1780     ip[20]    = 12;
1781     ip[21]    = 13;
1782     ip[22]    = 14;
1783     ip[23]    = 15;
1784     fp[24]    = 16.0f;
1785     fp[25]    = 0.0f;
1786     fp[26]    = 0.0f;
1787     fp[27]    = 0.0f;
1788     fp[28]    = 17.0f;
1789     fp[29]    = 18.0f;
1790     fp[30]    = 19.0f;
1791     fp[31]    = 0.0f;
1792     ip[32]    = 20;
1793     ip[33]    = 21;
1794     ip[34]    = 22;
1795     ip[35]    = 23;
1796 
1797     return NL "struct Struct0 {" NL "  ivec2 m0;" NL "};" NL "struct Struct1 {" NL "  vec3 m0;" NL "};" NL
1798               "struct Struct3 {" NL "  int m0;" NL "};" NL "struct Struct2 {" NL "  float m0;" NL "  Struct1 m1;" NL
1799               "  Struct0 m2;" NL "  int m3;" NL "  Struct3 m4;" NL "};" NL
1800               "layout(std430, binding = 0) buffer Input {" NL "  int data0;" NL "  Struct0 data1;" NL
1801               "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_input;" NL
1802               "layout(std430, binding = 1) buffer Output {" NL "  int data0;" NL "  Struct0 data1;" NL
1803               "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1804               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1805               "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
1806               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1807 }
1808 
1809 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1810 {
GetInput(std::vector<GLubyte> & in_data)1811     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1812     {
1813         return GetInput430c7(in_data);
1814     }
1815 };
1816 
1817 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1818 {
GetInput(std::vector<GLubyte> & in_data)1819     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1820     {
1821         return GetInput430c7(in_data);
1822     }
1823 };
1824 
1825 //-----------------------------------------------------------------------------
1826 // 1.7.1 BasicStd140LayoutCase1
1827 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1828 const char *GetInput140c1(std::vector<GLubyte> &in_data)
1829 {
1830     in_data.resize(8 * 4);
1831     float *fp = reinterpret_cast<float *>(&in_data[0]);
1832     fp[0]     = 1.0f;
1833     fp[1]     = 0.0f;
1834     fp[2]     = 0.0f;
1835     fp[3]     = 0.0f;
1836     fp[4]     = 2.0f;
1837 
1838     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "} g_input;" NL
1839               "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL "} g_output;" NL
1840               "void main() {" NL
1841               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1842 }
1843 
1844 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1845 {
GetInput(std::vector<GLubyte> & in_data)1846     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1847     {
1848         return GetInput140c1(in_data);
1849     }
1850 };
1851 
1852 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1853 {
GetInput(std::vector<GLubyte> & in_data)1854     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1855     {
1856         return GetInput140c1(in_data);
1857     }
1858 };
1859 //-----------------------------------------------------------------------------
1860 // 1.7.2 BasicStd140LayoutCase2
1861 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1862 const char *GetInput140c2(std::vector<GLubyte> &in_data)
1863 {
1864     in_data.resize(20 * 4);
1865     float *fp = reinterpret_cast<float *>(&in_data[0]);
1866     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1867     fp[0]     = 1.0f;
1868     fp[1]     = 0.0f;
1869     fp[2]     = 0.0f;
1870     fp[3]     = 0.0f;
1871     fp[4]     = 2.0f;
1872     fp[5]     = 0.0f;
1873     fp[6]     = 0.0f;
1874     fp[7]     = 0.0f;
1875     fp[8]     = 3.0f;
1876     fp[9]     = 0.0f;
1877     fp[10]    = 0.0f;
1878     fp[11]    = 0.0f;
1879     fp[12]    = 4.0f;
1880     fp[13]    = 0.0f;
1881     fp[14]    = 0.0f;
1882     fp[15]    = 0.0f;
1883     ip[16]    = 5;
1884     ip[17]    = 6;
1885 
1886     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1887               "  ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL
1888               "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1889               "  g_output.data0 = g_input.data0;" NL
1890               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1891               "  g_output.data2 = g_input.data2;" NL "}";
1892 }
1893 
1894 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1895 {
GetInput(std::vector<GLubyte> & in_data)1896     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1897     {
1898         return GetInput140c2(in_data);
1899     }
1900 };
1901 
1902 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1903 {
GetInput(std::vector<GLubyte> & in_data)1904     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1905     {
1906         return GetInput140c2(in_data);
1907     }
1908 };
1909 //-----------------------------------------------------------------------------
1910 // 1.7.3 BasicStd140LayoutCase3
1911 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1912 const char *GetInput140c3(std::vector<GLubyte> &in_data)
1913 {
1914     in_data.resize(32 * 4);
1915     float *fp = reinterpret_cast<float *>(&in_data[0]);
1916     fp[0]     = 1.0f;
1917     fp[1]     = 0.0f;
1918     fp[2]     = 0.0f;
1919     fp[3]     = 0.0f;
1920     fp[4]     = 2.0f;
1921     fp[5]     = 0.0f;
1922     fp[6]     = 0.0f;
1923     fp[7]     = 0.0f;
1924     fp[8]     = 3.0f;
1925     fp[9]     = 0.0f;
1926     fp[10]    = 0.0f;
1927     fp[11]    = 0.0f;
1928     fp[12]    = 4.0f;
1929     fp[13]    = 0.0f;
1930     fp[14]    = 0.0f;
1931     fp[15]    = 0.0f;
1932     fp[16]    = 5.0f;
1933     fp[17]    = 6.0f;
1934     fp[18]    = 0.0f;
1935     fp[19]    = 0.0f;
1936     fp[20]    = 7.0f;
1937     fp[21]    = 8.0f;
1938     fp[22]    = 9.0f;
1939     fp[23]    = 0.0f;
1940     fp[24]    = 10.0f;
1941     fp[25]    = 11.0f;
1942     fp[26]    = 12.0f;
1943     fp[27]    = 0.0f;
1944     fp[28]    = 13.0f;
1945 
1946     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1947               "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1948               "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1949               "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1950               "  g_output.data0 = g_input.data0;" NL
1951               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1952               "  g_output.data2 = g_input.data2;" NL
1953               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1954               "  g_output.data4 = g_input.data4;" NL "}";
1955 }
1956 
1957 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1958 {
GetInput(std::vector<GLubyte> & in_data)1959     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1960     {
1961         return GetInput140c3(in_data);
1962     }
1963 };
1964 
1965 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1966 {
GetInput(std::vector<GLubyte> & in_data)1967     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1968     {
1969         return GetInput140c3(in_data);
1970     }
1971 };
1972 
1973 //-----------------------------------------------------------------------------
1974 // 1.7.4 BasicStd140LayoutCase4
1975 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1976 const char *GetInput140c4(std::vector<GLubyte> &in_data)
1977 {
1978     in_data.resize(28 * 4);
1979     float *fp = reinterpret_cast<float *>(&in_data[0]);
1980     fp[0]     = 1.0f;
1981     fp[1]     = 2.0f;
1982     fp[2]     = 0.0f;
1983     fp[3]     = 0.0f;
1984     fp[4]     = 3.0f;
1985     fp[5]     = 4.0f;
1986     fp[6]     = 0.0f;
1987     fp[7]     = 0.0f;
1988     fp[8]     = 5.0f;
1989     fp[9]     = 6.0f;
1990     fp[10]    = 0.0f;
1991     fp[11]    = 0.0f;
1992     fp[12]    = 7.0f;
1993     fp[13]    = 8.0f;
1994     fp[14]    = 0.0f;
1995     fp[15]    = 0.0f;
1996     fp[16]    = 9.0f;
1997     fp[17]    = 10.0f;
1998     fp[18]    = 11.0f;
1999     fp[19]    = 0.0f;
2000     fp[20]    = 12.0f;
2001     fp[21]    = 13.0f;
2002     fp[22]    = 14.0f;
2003     fp[23]    = 0.0f;
2004     fp[24]    = 15.0f;
2005 
2006     return NL "layout(std140, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
2007               "  float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
2008               "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
2009               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
2010               "  g_output.data2 = g_input.data2;" NL "}";
2011 }
2012 
2013 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
2014 {
GetInput(std::vector<GLubyte> & in_data)2015     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2016     {
2017         return GetInput140c4(in_data);
2018     }
2019 };
2020 
2021 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
2022 {
GetInput(std::vector<GLubyte> & in_data)2023     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2024     {
2025         return GetInput140c4(in_data);
2026     }
2027 };
2028 //-----------------------------------------------------------------------------
2029 // 1.7.5 BasicStd140LayoutCase5
2030 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)2031 const char *GetInput140c5(std::vector<GLubyte> &in_data)
2032 {
2033     in_data.resize(8 * 4);
2034     float *fp = reinterpret_cast<float *>(&in_data[0]);
2035     fp[0]     = 1.0f;
2036     fp[1]     = 2.0f;
2037     fp[2]     = 3.0f;
2038     fp[3]     = 4.0f;
2039     fp[4]     = 5.0f;
2040     fp[5]     = 6.0f;
2041     fp[6]     = 7.0f;
2042     fp[7]     = 8.0f;
2043 
2044     return NL "layout(std140, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
2045               "layout(std140, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
2046               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
2047 }
2048 
2049 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
2050 {
GetInput(std::vector<GLubyte> & in_data)2051     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2052     {
2053         return GetInput140c5(in_data);
2054     }
2055 };
2056 
2057 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2058 {
GetInput(std::vector<GLubyte> & in_data)2059     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2060     {
2061         return GetInput140c5(in_data);
2062     }
2063 };
2064 
2065 //-----------------------------------------------------------------------------
2066 // 1.7.6 BasicStd140LayoutCase6
2067 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2068 const char *GetInput140c6(std::vector<GLubyte> &in_data)
2069 {
2070     in_data.resize(96 * 4);
2071     float *fp = reinterpret_cast<float *>(&in_data[0]);
2072     fp[0]     = 1.0f;
2073     fp[1]     = 0.0f;
2074     fp[2]     = 0.0f;
2075     fp[3]     = 0.0f;
2076     fp[4]     = 2.0f;
2077     fp[5]     = 0.0f;
2078     fp[6]     = 0.0f;
2079     fp[7]     = 0.0f;
2080     fp[8]     = 3.0f;
2081     fp[9]     = 0.0f;
2082     fp[10]    = 0.0f;
2083     fp[11]    = 0.0f;
2084     fp[12]    = 4.0f;
2085     fp[13]    = 0.0f;
2086     fp[14]    = 0.0f;
2087     fp[15]    = 0.0f;
2088     fp[16]    = 5.0f;
2089     fp[17]    = 0.0f;
2090     fp[18]    = 0.0f;
2091     fp[19]    = 0.0f;
2092     fp[20]    = 6.0f;
2093     fp[21]    = 7.0f;
2094     fp[22]    = 8.0f;
2095     fp[23]    = 9.0f;
2096     fp[24]    = 10.0f;
2097     fp[25]    = 11.0f;
2098     fp[26]    = 0.0f;
2099     fp[27]    = 0.0f;
2100     fp[28]    = 12.0f;
2101     fp[29]    = 13.0f;
2102     fp[30]    = 0.0f;
2103     fp[31]    = 0.0f;
2104     fp[32]    = 14.0f;
2105     fp[33]    = 15.0f;
2106     fp[34]    = 0.0f;
2107     fp[35]    = 0.0f;
2108     fp[36]    = 16.0f;
2109     fp[37]    = 17.0f;
2110     fp[38]    = 0.0f;
2111     fp[39]    = 0.0f;
2112     fp[40]    = 18.0f;
2113     fp[41]    = 19.0f;
2114     fp[42]    = 20.0f;
2115     fp[43]    = 0.0f;
2116     fp[44]    = 21.0f;
2117     fp[45]    = 22.0f;
2118     fp[46]    = 23.0f;
2119     fp[47]    = 0.0f;
2120     fp[48]    = 24.0f;
2121     fp[49]    = 25.0f;
2122     fp[50]    = 26.0f;
2123     fp[51]    = 0.0f;
2124     fp[52]    = 27.0f;
2125     fp[53]    = 28.0f;
2126     fp[54]    = 29.0f;
2127     fp[55]    = 0.0f;
2128     fp[56]    = 30.0f;
2129     fp[57]    = 31.0f;
2130     fp[58]    = 32.0f;
2131     fp[59]    = 0.0f;
2132     fp[60]    = 33.0f;
2133     fp[61]    = 34.0f;
2134     fp[62]    = 35.0f;
2135     fp[63]    = 0.0f;
2136     fp[64]    = 36.0f;
2137     fp[65]    = 37.0f;
2138     fp[66]    = 38.0f;
2139     fp[67]    = 39.0f;
2140     fp[68]    = 40.0f;
2141     fp[69]    = 41.0f;
2142     fp[70]    = 42.0f;
2143     fp[71]    = 43.0f;
2144     fp[72]    = 44.0f;
2145     fp[73]    = 45.0f;
2146     fp[74]    = 46.0f;
2147     fp[75]    = 47.0f;
2148     fp[76]    = 48.0f;
2149     fp[77]    = 49.0f;
2150     fp[78]    = 50.0f;
2151     fp[79]    = 51.0f;
2152     fp[80]    = 52.0f;
2153     fp[81]    = 68.0f;
2154     fp[82]    = 69.0f;
2155     fp[83]    = 70.0f;
2156     fp[84]    = 56.0f;
2157     fp[85]    = 72.0f;
2158     fp[86]    = 73.0f;
2159     fp[87]    = 74.0f;
2160     fp[88]    = 60.0f;
2161     fp[89]    = 76.0f;
2162     fp[90]    = 77.0f;
2163     fp[91]    = 78.0f;
2164     fp[92]    = 64.0f;
2165     fp[93]    = 80.0f;
2166     fp[94]    = 81.0f;
2167     fp[95]    = 82.0f;
2168 
2169     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
2170               "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL "  mat4 data6[2];" NL
2171               "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL
2172               "  float data1[3];" NL "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL
2173               "  mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2174               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2175               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2176               "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
2177               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2178               "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2179               "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2180 }
2181 
2182 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2183 {
GetInput(std::vector<GLubyte> & in_data)2184     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2185     {
2186         return GetInput140c6(in_data);
2187     }
2188 };
2189 
2190 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2191 {
GetInput(std::vector<GLubyte> & in_data)2192     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2193     {
2194         return GetInput140c6(in_data);
2195     }
2196 };
2197 
2198 //-----------------------------------------------------------------------------
2199 // 1.8.1 BasicAtomicCase1
2200 //-----------------------------------------------------------------------------
2201 class BasicAtomicCase1 : public ShaderStorageBufferObjectBase
2202 {
2203     GLuint m_program;
2204     GLuint m_storage_buffer[6];
2205     GLuint m_vertex_array;
2206     GLuint m_vertex_buffer;
2207 
Setup()2208     virtual long Setup()
2209     {
2210         m_program = 0;
2211         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2212         m_vertex_array  = 0;
2213         m_vertex_buffer = 0;
2214         return NO_ERROR;
2215     }
2216 
Run()2217     virtual long Run()
2218     {
2219         if (!SupportedInVS(2))
2220             return NOT_SUPPORTED;
2221         if (!SupportedInGS(2))
2222             return NOT_SUPPORTED;
2223 
2224         const char *const glsl_vs =
2225             NL "layout(location = 0) in vec4 g_in_position;" NL
2226                "layout(std430, binding = 0) coherent buffer VSuint {" NL "  uint g_uint_out[4];" NL "};" NL
2227                "layout(std430, binding = 1) coherent buffer VSint {" NL "  int data[4];" NL "} g_int_out;" NL
2228                "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2229                "  gl_Position = g_in_position;" NL NL
2230                "  if (atomicExchange(g_uint_out[gl_VertexID], g_uint_value[1]) != 0u) return;" NL
2231                "  if (atomicAdd(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2232                "  if (atomicMin(g_uint_out[gl_VertexID], g_uint_value[1]) != 3u) return;" NL
2233                "  if (atomicMax(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2234                "  if (atomicAnd(g_uint_out[gl_VertexID], g_uint_value[3]) != 2u) return;" NL
2235                "  if (atomicOr(g_uint_out[gl_VertexID], g_uint_value[4]) != 0u) return;" NL
2236                "  if (g_uint_value[0] > 0u) {" NL
2237                "    if (atomicXor(g_uint_out[gl_VertexID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2238                "  if (atomicCompSwap(g_uint_out[gl_VertexID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2239                "    g_uint_out[gl_VertexID] = 1u;" NL "    return;" NL "  }" NL NL
2240                "  if (atomicExchange(g_int_out.data[gl_VertexID], 1) != 0) return;" NL
2241                "  if (atomicAdd(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2242                "  if (atomicMin(g_int_out.data[gl_VertexID], 1) != 3) return;" NL
2243                "  if (atomicMax(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2244                "  if (atomicAnd(g_int_out.data[gl_VertexID], 0x1) != 2) return;" NL
2245                "  if (atomicOr(g_int_out.data[gl_VertexID], 0x3) != 0) return;" NL
2246                "  if (atomicXor(g_int_out.data[gl_VertexID], 0x1) != 3) return;" NL
2247                "  if (atomicCompSwap(g_int_out.data[gl_VertexID], 0x2, 0x7) != 2) {" NL
2248                "    g_int_out.data[gl_VertexID] = 1;" NL "    return;" NL "  }" NL "}";
2249 
2250         const char *const glsl_gs = NL
2251             "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2252             "layout(std430, binding = 2) coherent buffer GSuint {" NL "  uint data[4];" NL "} g_uint_gs;" NL
2253             "layout(std430, binding = 3) coherent buffer GSint {" NL "  int data[4];" NL "} g_int_gs;" NL
2254             "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2255             "  gl_Position = gl_in[0].gl_Position;" NL "  gl_PrimitiveID = gl_PrimitiveIDIn;" NL "  EmitVertex();" NL NL
2256             "  if (atomicExchange(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 0u) return;" NL
2257             "  if (atomicAdd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2258             "  if (atomicMin(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 3u) return;" NL
2259             "  if (atomicMax(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2260             "  if (atomicAnd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[3]) != 2u) return;" NL
2261             "  if (atomicOr(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[4]) != 0u) return;" NL
2262             "  if (g_uint_value[0] > 0u) {" NL
2263             "    if (atomicXor(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[5]) != 3u) return;" NL "  }" NL
2264             "  if (atomicCompSwap(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2265             "    g_uint_gs.data[gl_PrimitiveIDIn] = 1u;" NL "    return;" NL "  }" NL NL
2266             "  if (atomicExchange(g_int_gs.data[gl_PrimitiveIDIn], 1) != 0) return;" NL
2267             "  if (atomicAdd(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2268             "  if (atomicMin(g_int_gs.data[gl_PrimitiveIDIn], 1) != 3) return;" NL
2269             "  if (atomicMax(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2270             "  if (atomicAnd(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 2) return;" NL
2271             "  if (atomicOr(g_int_gs.data[gl_PrimitiveIDIn], 0x3) != 0) return;" NL
2272             "  if (atomicXor(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 3) return;" NL
2273             "  if (atomicCompSwap(g_int_gs.data[gl_PrimitiveIDIn], 0x2, 0x7) != 2) {" NL
2274             "    g_int_gs.data[gl_PrimitiveIDIn] = 1;" NL "    return;" NL "  }" NL "}";
2275 
2276         const char *const glsl_fs =
2277             NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 4) coherent buffer FSuint {" NL
2278                "  uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 5) coherent buffer FSint {" NL
2279                "  int data[4];" NL "} g_int_fs;" NL
2280                "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2281                "  g_fs_out = vec4(0, 1, 0, 1);" NL NL
2282                "  if (atomicExchange(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2283                "  if (atomicAdd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2284                "  if (atomicMin(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2285                "  if (atomicMax(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2286                "  if (atomicAnd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2287                "  if (atomicOr(g_uint_fs.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2288                "  if (g_uint_value[0] > 0u) {" NL
2289                "    if (atomicXor(g_uint_fs.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2290                "  if (atomicCompSwap(g_uint_fs.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2291                "    g_uint_fs.data[gl_PrimitiveID] = 1u;" NL "    return;" NL "  }" NL NL
2292                "  if (atomicExchange(g_int_fs.data[gl_PrimitiveID], 1) != 0) return;" NL
2293                "  if (atomicAdd(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2294                "  if (atomicMin(g_int_fs.data[gl_PrimitiveID], 1) != 3) return;" NL
2295                "  if (atomicMax(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2296                "  if (atomicAnd(g_int_fs.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2297                "  if (atomicOr(g_int_fs.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2298                "  if (atomicXor(g_int_fs.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2299                "  if (atomicCompSwap(g_int_fs.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2300                "    g_int_fs.data[gl_PrimitiveID] = 1;" NL "    return;" NL "  }" NL "}";
2301         m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2302         glLinkProgram(m_program);
2303         if (!CheckProgram(m_program))
2304             return ERROR;
2305 
2306         glGenBuffers(6, m_storage_buffer);
2307         for (GLuint i = 0; i < 6; ++i)
2308         {
2309             const int data[4] = {0};
2310             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2311             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2312         }
2313 
2314         /* vertex buffer */
2315         {
2316             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2317             glGenBuffers(1, &m_vertex_buffer);
2318             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2319             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2320             glBindBuffer(GL_ARRAY_BUFFER, 0);
2321         }
2322 
2323         glGenVertexArrays(1, &m_vertex_array);
2324         glBindVertexArray(m_vertex_array);
2325         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2326         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2327         glBindBuffer(GL_ARRAY_BUFFER, 0);
2328         glEnableVertexAttribArray(0);
2329         glBindVertexArray(0);
2330 
2331         glClear(GL_COLOR_BUFFER_BIT);
2332         glUseProgram(m_program);
2333         glBindVertexArray(m_vertex_array);
2334         glDrawArrays(GL_POINTS, 0, 4);
2335         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2336 
2337         for (int ii = 0; ii < 3; ++ii)
2338         {
2339             /* uint data */
2340             {
2341                 GLuint data[4];
2342                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2343                 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2344                 for (GLuint i = 0; i < 4; ++i)
2345                 {
2346                     if (data[i] != 7)
2347                     {
2348                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2349                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2350                         return ERROR;
2351                     }
2352                 }
2353             }
2354             /* int data */
2355             {
2356                 GLint data[4];
2357                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2358                 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2359                 for (GLint i = 0; i < 4; ++i)
2360                 {
2361                     if (data[i] != 7)
2362                     {
2363                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2364                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2365                         return ERROR;
2366                     }
2367                 }
2368             }
2369         }
2370         return NO_ERROR;
2371     }
2372 
Cleanup()2373     virtual long Cleanup()
2374     {
2375         glUseProgram(0);
2376         glDeleteProgram(m_program);
2377         glDeleteBuffers(6, m_storage_buffer);
2378         glDeleteBuffers(1, &m_vertex_buffer);
2379         glDeleteVertexArrays(1, &m_vertex_array);
2380         return NO_ERROR;
2381     }
2382 };
2383 
2384 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2385 {
2386     GLuint m_program;
2387     GLuint m_storage_buffer[2];
2388 
Setup()2389     virtual long Setup()
2390     {
2391         m_program = 0;
2392         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2393         return NO_ERROR;
2394     }
2395 
Run()2396     virtual long Run()
2397     {
2398         const char *const glsl_cs =
2399             NL "layout(local_size_x = 4) in;" NL "layout(std430, binding = 2) coherent buffer FSuint {" NL
2400                "  uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 3) coherent buffer FSint {" NL
2401                "  int data[4];" NL "} g_int_fs;" NL "uniform uint g_uint_value[8];" NL "void main() {" NL
2402                "  if (atomicExchange(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 0u) return;" NL
2403                "  if (atomicAdd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2404                "  if (atomicMin(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 3u) return;" NL
2405                "  if (atomicMax(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2406                "  if (atomicAnd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[3]) != 2u) return;" NL
2407                "  if (atomicOr(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[4]) != 0u) return;" NL
2408                "  if (g_uint_value[0] > 0u) {" NL
2409                "    if (atomicXor(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[5]) != 3u) return;" NL "  }" NL
2410                "  if (atomicCompSwap(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[6], g_uint_value[7]) != 2u) "
2411                "{" NL "    g_uint_fs.data[gl_LocalInvocationIndex] = 1u;" NL "    return;" NL "  }" NL
2412                "  if (atomicExchange(g_int_fs.data[gl_LocalInvocationIndex], 1) != 0) return;" NL
2413                "  if (atomicAdd(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2414                "  if (atomicMin(g_int_fs.data[gl_LocalInvocationIndex], 1) != 3) return;" NL
2415                "  if (atomicMax(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2416                "  if (atomicAnd(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 2) return;" NL
2417                "  if (atomicOr(g_int_fs.data[gl_LocalInvocationIndex], 0x3) != 0) return;" NL
2418                "  if (atomicXor(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 3) return;" NL
2419                "  if (atomicCompSwap(g_int_fs.data[gl_LocalInvocationIndex], 0x2, 0x7) != 2) {" NL
2420                "    g_int_fs.data[gl_LocalInvocationIndex] = 1;" NL "    return;" NL "  }" NL "}";
2421         m_program = CreateProgramCS(glsl_cs);
2422         glLinkProgram(m_program);
2423         if (!CheckProgram(m_program))
2424             return ERROR;
2425 
2426         glGenBuffers(2, m_storage_buffer);
2427         for (GLuint i = 0; i < 2; ++i)
2428         {
2429             const int data[4] = {0};
2430             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 2, m_storage_buffer[i]);
2431             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2432         }
2433 
2434         glUseProgram(m_program);
2435         GLuint unif[8] = {3, 1, 2, 1, 3, 1, 2, 7};
2436         glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2437         glDispatchCompute(1, 1, 1);
2438         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2439 
2440         /* uint data */
2441         {
2442             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
2443             GLuint *data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2444             if (!data)
2445                 return ERROR;
2446             for (GLuint i = 0; i < 4; ++i)
2447             {
2448                 if (data[i] != 7)
2449                 {
2450                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2451                                                         << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2452                     return ERROR;
2453                 }
2454             }
2455             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2456         }
2457         /* int data */
2458         {
2459             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
2460             GLint *data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2461             if (!data)
2462                 return ERROR;
2463             for (GLint i = 0; i < 4; ++i)
2464             {
2465                 if (data[i] != 7)
2466                 {
2467                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2468                                                         << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2469                     return ERROR;
2470                 }
2471             }
2472             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2473         }
2474         return NO_ERROR;
2475     }
2476 
Cleanup()2477     virtual long Cleanup()
2478     {
2479         glUseProgram(0);
2480         glDeleteProgram(m_program);
2481         glDeleteBuffers(2, m_storage_buffer);
2482         return NO_ERROR;
2483     }
2484 };
2485 //-----------------------------------------------------------------------------
2486 // 1.8.2 BasicAtomicCase2
2487 //-----------------------------------------------------------------------------
2488 class BasicAtomicCase2 : public ShaderStorageBufferObjectBase
2489 {
2490     GLuint m_program;
2491     GLuint m_storage_buffer[4];
2492     GLuint m_vertex_array;
2493     GLuint m_vertex_buffer;
2494 
Setup()2495     virtual long Setup()
2496     {
2497         m_program = 0;
2498         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2499         m_vertex_array  = 0;
2500         m_vertex_buffer = 0;
2501         return NO_ERROR;
2502     }
2503 
Run()2504     virtual long Run()
2505     {
2506         if (!SupportedInTCS(2))
2507             return NOT_SUPPORTED;
2508         if (!SupportedInTES(2))
2509             return NOT_SUPPORTED;
2510 
2511         const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
2512                                        "  gl_Position = g_in_position;" NL "}";
2513 
2514         const char *const glsl_tcs = NL
2515             "layout(vertices = 1) out;" NL "layout(std430, binding = 0) buffer TCSuint {" NL "  uint g_uint_out[1];" NL
2516             "};" NL "layout(std430, binding = 1) buffer TCSint {" NL "  int data[1];" NL "} g_int_out;" NL
2517             "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2518             "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;" NL
2519             "  if (gl_InvocationID == 0) {" NL "    gl_TessLevelInner[0] = 1.0;" NL "    gl_TessLevelInner[1] = 1.0;" NL
2520             "    gl_TessLevelOuter[0] = 1.0;" NL "    gl_TessLevelOuter[1] = 1.0;" NL
2521             "    gl_TessLevelOuter[2] = 1.0;" NL "    gl_TessLevelOuter[3] = 1.0;" NL "  }" NL
2522             "  if (atomicAdd(g_uint_out[gl_InvocationID], g_uint_value[0]) != 0u) return;" NL
2523             "  if (atomicExchange(g_uint_out[gl_InvocationID], g_uint_value[0]) != 3u) return;" NL
2524             "  if (atomicMin(g_uint_out[gl_InvocationID], g_uint_value[1]) != 3u) return;" NL
2525             "  if (atomicMax(g_uint_out[gl_InvocationID], g_uint_value[2]) != 1u) return;" NL
2526             "  if (atomicAnd(g_uint_out[gl_InvocationID], g_uint_value[3]) != 2u) return;" NL
2527             "  if (atomicOr(g_uint_out[gl_InvocationID], g_uint_value[4]) != 0u) return;" NL
2528             "  if (g_uint_value[0] > 0u) {" NL
2529             "    if (atomicXor(g_uint_out[gl_InvocationID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2530             "  if (atomicCompSwap(g_uint_out[gl_InvocationID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2531             "    g_uint_out[gl_InvocationID] = 1u;" NL "    return;" NL "  }" NL NL
2532             "  if (atomicAdd(g_int_out.data[gl_InvocationID], 3) != 0) return;" NL
2533             "  if (atomicExchange(g_int_out.data[gl_InvocationID], 3) != 3) return;" NL
2534             "  if (atomicMin(g_int_out.data[gl_InvocationID], 1) != 3) return;" NL
2535             "  if (atomicMax(g_int_out.data[gl_InvocationID], 2) != 1) return;" NL
2536             "  if (atomicAnd(g_int_out.data[gl_InvocationID], 0x1) != 2) return;" NL
2537             "  if (atomicOr(g_int_out.data[gl_InvocationID], 0x3) != 0) return;" NL
2538             "  if (atomicXor(g_int_out.data[gl_InvocationID], 0x1) != 3) return;" NL
2539             "  if (atomicCompSwap(g_int_out.data[gl_InvocationID], 0x2, 0x7) != 2) {" NL
2540             "    g_int_out.data[gl_InvocationID] = 1;" NL "    return;" NL "  }" NL "}";
2541 
2542         const char *const glsl_tes =
2543             NL "layout(quads, point_mode) in;" NL "layout(std430, binding = 2) buffer TESuint {" NL "  uint data[1];" NL
2544                "} g_uint_tes;" NL "layout(std430, binding = 3) buffer TESint {" NL "  int data[1];" NL "} g_int_tes;" NL
2545                "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2546                "  gl_Position = gl_in[0].gl_Position;" NL NL
2547                "  if (atomicExchange(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2548                "  if (atomicAdd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2549                "  if (atomicMin(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2550                "  if (atomicMax(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2551                "  if (atomicAnd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2552                "  if (atomicOr(g_uint_tes.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2553                "  if (g_uint_value[0] > 0u) {" NL
2554                "    if (atomicXor(g_uint_tes.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2555                "  if (atomicCompSwap(g_uint_tes.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2556                "    g_uint_tes.data[gl_PrimitiveID] = 1u;" NL "    return;" NL "  }" NL NL
2557                "  if (atomicExchange(g_int_tes.data[gl_PrimitiveID], 1) != 0) return;" NL
2558                "  if (atomicAdd(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2559                "  if (atomicMin(g_int_tes.data[gl_PrimitiveID], 1) != 3) return;" NL
2560                "  if (atomicMax(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2561                "  if (atomicAnd(g_int_tes.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2562                "  if (atomicOr(g_int_tes.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2563                "  if (atomicXor(g_int_tes.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2564                "  if (atomicCompSwap(g_int_tes.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2565                "    g_int_tes.data[gl_PrimitiveID] = 1;" NL "    return;" NL "  }" NL "}";
2566 
2567         const char *const glsl_fs =
2568             NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
2569 
2570         m_program = CreateProgram(glsl_vs, glsl_tcs, glsl_tes, "", glsl_fs);
2571         glLinkProgram(m_program);
2572         if (!CheckProgram(m_program))
2573             return ERROR;
2574 
2575         glGenBuffers(4, m_storage_buffer);
2576         for (GLuint i = 0; i < 4; ++i)
2577         {
2578             const int data[1] = {0};
2579             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2580             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2581         }
2582 
2583         /* vertex buffer */
2584         {
2585             const float data[2] = {0.0f, 0.0f};
2586             glGenBuffers(1, &m_vertex_buffer);
2587             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2588             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2589             glBindBuffer(GL_ARRAY_BUFFER, 0);
2590         }
2591 
2592         glGenVertexArrays(1, &m_vertex_array);
2593         glBindVertexArray(m_vertex_array);
2594         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2595         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2596         glBindBuffer(GL_ARRAY_BUFFER, 0);
2597         glEnableVertexAttribArray(0);
2598         glBindVertexArray(0);
2599 
2600         glClear(GL_COLOR_BUFFER_BIT);
2601         glUseProgram(m_program);
2602         glBindVertexArray(m_vertex_array);
2603         glPatchParameteri(GL_PATCH_VERTICES, 1);
2604         glDrawArrays(GL_PATCHES, 0, 1);
2605         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2606 
2607         for (int ii = 0; ii < 2; ++ii)
2608         {
2609             /* uint data */
2610             {
2611                 GLuint data[1];
2612                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2613                 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2614                 for (GLuint i = 0; i < 1; ++i)
2615                 {
2616                     if (data[i] != 7)
2617                     {
2618                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2619                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2620                         return ERROR;
2621                     }
2622                 }
2623             }
2624             /* int data */
2625             {
2626                 GLint data[1];
2627                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2628                 glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2629                 for (GLint i = 0; i < 1; ++i)
2630                 {
2631                     if (data[i] != 7)
2632                     {
2633                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2634                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2635                         return ERROR;
2636                     }
2637                 }
2638             }
2639         }
2640         return NO_ERROR;
2641     }
2642 
Cleanup()2643     virtual long Cleanup()
2644     {
2645         glPatchParameteri(GL_PATCH_VERTICES, 3);
2646         glUseProgram(0);
2647         glDeleteProgram(m_program);
2648         glDeleteBuffers(4, m_storage_buffer);
2649         glDeleteBuffers(1, &m_vertex_buffer);
2650         glDeleteVertexArrays(1, &m_vertex_array);
2651         return NO_ERROR;
2652     }
2653 };
2654 
2655 //-----------------------------------------------------------------------------
2656 // 1.8.3 BasicAtomicCase3
2657 //-----------------------------------------------------------------------------
2658 class BasicAtomicCase3 : public ShaderStorageBufferObjectBase
2659 {
2660     GLuint m_program;
2661     GLuint m_storage_buffer;
2662     GLuint m_vertex_array;
2663     GLuint m_vertex_buffer;
2664 
Setup()2665     virtual long Setup()
2666     {
2667         m_program        = 0;
2668         m_storage_buffer = 0;
2669         m_vertex_array   = 0;
2670         m_vertex_buffer  = 0;
2671         return NO_ERROR;
2672     }
2673 
Run()2674     virtual long Run()
2675     {
2676         if (!SupportedInVS(1))
2677             return NOT_SUPPORTED;
2678         if (!SupportedInGS(1))
2679             return NOT_SUPPORTED;
2680 
2681         const char *const glsl_vs =
2682             NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2683                "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_vs_buffer;" NL "void main() {" NL
2684                "  gl_Position = g_in_position;" NL "  atomicAdd(g_vs_buffer.u[0].x, g_vs_buffer.u[gl_VertexID][1]);" NL
2685                "  atomicAdd(g_vs_buffer.u[0][0], g_vs_buffer.u[gl_VertexID].z);" NL
2686                "  atomicAdd(g_vs_buffer.i[0].x, g_vs_buffer.i[gl_VertexID][1]);" NL
2687                "  atomicAdd(g_vs_buffer.i[0][0], g_vs_buffer.i[gl_VertexID].z);" NL "}";
2688 
2689         const char *const glsl_gs = NL
2690             "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2691             "layout(std430, binding = 0) buffer Buffer {" NL "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_gs_buffer;" NL
2692             "void main() {" NL "  gl_Position = gl_in[0].gl_Position;" NL "  gl_PrimitiveID = gl_PrimitiveIDIn;" NL
2693             "  EmitVertex();" NL "  atomicAdd(g_gs_buffer.u[0].x, g_gs_buffer.u[gl_PrimitiveIDIn][1]);" NL
2694             "  atomicAdd(g_gs_buffer.i[0].x, g_gs_buffer.i[gl_PrimitiveIDIn][1]);" NL "}";
2695 
2696         const char *const glsl_fs = NL
2697             "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2698             "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2699             "  g_fs_out = vec4(0, 1, 0, 1);" NL "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_PrimitiveID][1]);" NL
2700             "  atomicAdd(g_fs_buffer.i[0].x, g_fs_buffer.i[gl_PrimitiveID][1]);" NL "}";
2701 
2702         m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2703         glLinkProgram(m_program);
2704         if (!CheckProgram(m_program))
2705             return ERROR;
2706 
2707         /* init storage buffer */
2708         {
2709             glGenBuffers(1, &m_storage_buffer);
2710             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2711             glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2712             ivec4 *ptr = reinterpret_cast<ivec4 *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2713             if (!ptr)
2714                 return ERROR;
2715             for (int i = 0; i < 4; ++i)
2716             {
2717                 ptr[i * 2]     = ivec4(0, 1, 2, 0);
2718                 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2719             }
2720             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2721         }
2722 
2723         /* init vertex buffer */
2724         {
2725             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2726             glGenBuffers(1, &m_vertex_buffer);
2727             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2728             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2729             glBindBuffer(GL_ARRAY_BUFFER, 0);
2730         }
2731 
2732         glGenVertexArrays(1, &m_vertex_array);
2733         glBindVertexArray(m_vertex_array);
2734         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2735         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2736         glBindBuffer(GL_ARRAY_BUFFER, 0);
2737         glEnableVertexAttribArray(0);
2738         glBindVertexArray(0);
2739 
2740         glClear(GL_COLOR_BUFFER_BIT);
2741         glUseProgram(m_program);
2742         glBindVertexArray(m_vertex_array);
2743         glDrawArrays(GL_POINTS, 0, 4);
2744         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2745 
2746         GLuint u;
2747         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &u);
2748         if (u != 20)
2749         {
2750             m_context.getTestContext().getLog()
2751                 << tcu::TestLog::Message << "Data at offset 0 is " << u << " should be 20." << tcu::TestLog::EndMessage;
2752             return ERROR;
2753         }
2754         GLint i;
2755         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLuint) * 4, 4, &i);
2756         if (i != 20)
2757         {
2758             m_context.getTestContext().getLog()
2759                 << tcu::TestLog::Message << "Data at offset 0 is " << i << " should be 20." << tcu::TestLog::EndMessage;
2760             return ERROR;
2761         }
2762 
2763         return NO_ERROR;
2764     }
2765 
Cleanup()2766     virtual long Cleanup()
2767     {
2768         glUseProgram(0);
2769         glDeleteProgram(m_program);
2770         glDeleteBuffers(1, &m_storage_buffer);
2771         glDeleteBuffers(1, &m_vertex_buffer);
2772         glDeleteVertexArrays(1, &m_vertex_array);
2773         return NO_ERROR;
2774     }
2775 };
2776 
2777 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2778 {
2779     GLuint m_program;
2780     GLuint m_storage_buffer;
2781 
Setup()2782     virtual long Setup()
2783     {
2784         m_program        = 0;
2785         m_storage_buffer = 0;
2786         return NO_ERROR;
2787     }
2788 
Run()2789     virtual long Run()
2790     {
2791         const char *const glsl_cs =
2792             NL "layout(local_size_y = 4) in;" NL "layout(std430) coherent buffer Buffer {" NL "  uvec4 u[4];" NL
2793                "  ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2794                "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y][2]);" NL
2795                "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y][1]);" NL
2796                "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y].z);" NL
2797                "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y].y);" NL "}";
2798         m_program = CreateProgramCS(glsl_cs);
2799         glLinkProgram(m_program);
2800         if (!CheckProgram(m_program))
2801             return ERROR;
2802 
2803         /* init storage buffer */
2804         {
2805             glGenBuffers(1, &m_storage_buffer);
2806             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2807             glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2808             ivec4 *ptr = reinterpret_cast<ivec4 *>(
2809                 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2810             if (!ptr)
2811                 return ERROR;
2812             for (int i = 0; i < 4; ++i)
2813             {
2814                 ptr[i * 2]     = ivec4(0, 1, 2, 0);
2815                 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2816             }
2817             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2818         }
2819 
2820         glUseProgram(m_program);
2821         glDispatchCompute(1, 1, 1);
2822         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2823 
2824         GLuint *u = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2825         if (!u)
2826             return ERROR;
2827         if (*u != 16)
2828         {
2829             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2830                                                 << " should be 16." << tcu::TestLog::EndMessage;
2831             return ERROR;
2832         }
2833         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2834         GLint *i = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2835         if (!i)
2836             return ERROR;
2837         if (*i != 16)
2838         {
2839             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2840                                                 << " should be 16." << tcu::TestLog::EndMessage;
2841             return ERROR;
2842         }
2843         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2844 
2845         return NO_ERROR;
2846     }
2847 
Cleanup()2848     virtual long Cleanup()
2849     {
2850         glUseProgram(0);
2851         glDeleteProgram(m_program);
2852         glDeleteBuffers(1, &m_storage_buffer);
2853         return NO_ERROR;
2854     }
2855 };
2856 //-----------------------------------------------------------------------------
2857 // 1.8.4 BasicAtomicCase4
2858 //-----------------------------------------------------------------------------
2859 
2860 class BasicAtomicCase4 : public ShaderStorageBufferObjectBase
2861 {
2862     GLuint m_program;
2863     GLuint m_storage_buffer[2];
2864     GLuint m_vertex_array;
2865     GLuint m_vertex_buffer;
2866 
Setup()2867     virtual long Setup()
2868     {
2869         m_program = 0;
2870         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2871         m_vertex_array  = 0;
2872         m_vertex_buffer = 0;
2873         return NO_ERROR;
2874     }
2875 
Run()2876     virtual long Run()
2877     {
2878         if (!SupportedInVS(2))
2879             return NOT_SUPPORTED;
2880 
2881         const char *const glsl_vs =
2882             NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Counters {" NL
2883                "  uint g_uint_counter;" NL "  int g_int_counter;" NL "};" NL
2884                "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL "  int idata[8];" NL
2885                "} g_output;" NL "void main() {" NL "  gl_Position = g_in_position;" NL
2886                "  const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2887                "  const int iidx = atomicAdd(g_int_counter, -1);" NL "  g_output.udata[uidx] = uidx;" NL
2888                "  g_output.idata[iidx] = iidx;" NL "}";
2889 
2890         const char *const glsl_fs =
2891             NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Counters {" NL
2892                "  uint g_uint_counter;" NL "  int g_int_counter;" NL "};" NL
2893                "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL "  int idata[8];" NL
2894                "} g_output;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL
2895                "  const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2896                "  const int iidx = atomicAdd(g_int_counter, -1);" NL "  g_output.udata[uidx] = uidx;" NL
2897                "  g_output.idata[iidx] = iidx;" NL "}";
2898         m_program = CreateProgram(glsl_vs, glsl_fs);
2899         glLinkProgram(m_program);
2900         if (!CheckProgram(m_program))
2901             return ERROR;
2902 
2903         glGenBuffers(2, m_storage_buffer);
2904         /* counter buffer */
2905         {
2906             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2907             glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2908             int *ptr = reinterpret_cast<int *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2909             if (!ptr)
2910                 return ERROR;
2911             *ptr++ = 0;
2912             *ptr++ = 7;
2913             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2914         }
2915         /* output buffer */
2916         {
2917             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2918             glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2919         }
2920         /* vertex buffer */
2921         {
2922             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2923             glGenBuffers(1, &m_vertex_buffer);
2924             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2925             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2926             glBindBuffer(GL_ARRAY_BUFFER, 0);
2927         }
2928 
2929         glGenVertexArrays(1, &m_vertex_array);
2930         glBindVertexArray(m_vertex_array);
2931         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2932         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2933         glBindBuffer(GL_ARRAY_BUFFER, 0);
2934         glEnableVertexAttribArray(0);
2935         glBindVertexArray(0);
2936 
2937         glClear(GL_COLOR_BUFFER_BIT);
2938         glUseProgram(m_program);
2939         glBindVertexArray(m_vertex_array);
2940         glDrawArrays(GL_POINTS, 0, 4);
2941         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2942 
2943         GLuint udata[8];
2944         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(udata), udata);
2945         for (GLuint i = 0; i < 8; ++i)
2946         {
2947             if (udata[i] != i)
2948             {
2949                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2950                                                     << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2951                 return ERROR;
2952             }
2953         }
2954         GLint idata[8];
2955         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(udata), sizeof(idata), idata);
2956         for (GLint i = 0; i < 8; ++i)
2957         {
2958             if (idata[i] != i)
2959             {
2960                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2961                                                     << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2962                 return ERROR;
2963             }
2964         }
2965         return NO_ERROR;
2966     }
2967 
Cleanup()2968     virtual long Cleanup()
2969     {
2970         glUseProgram(0);
2971         glDeleteProgram(m_program);
2972         glDeleteBuffers(2, m_storage_buffer);
2973         glDeleteBuffers(1, &m_vertex_buffer);
2974         glDeleteVertexArrays(1, &m_vertex_array);
2975         return NO_ERROR;
2976     }
2977 };
2978 
2979 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2980 {
2981     GLuint m_program;
2982     GLuint m_storage_buffer[2];
2983 
Setup()2984     virtual long Setup()
2985     {
2986         m_program = 0;
2987         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2988         return NO_ERROR;
2989     }
2990 
Run()2991     virtual long Run()
2992     {
2993         const char *const glsl_cs =
2994             NL "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;" NL
2995                "layout(std430, binding = 0) coherent buffer Counters {" NL "  uint g_uint_counter;" NL
2996                "  int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL
2997                "  int idata[8];" NL "} g_output;" NL "void main() {" NL
2998                "  uint uidx = atomicAdd(g_uint_counter, 1u);" NL "  int iidx = atomicAdd(g_int_counter, -1);" NL
2999                "  g_output.udata[uidx] = uidx;" NL "  g_output.idata[iidx] = iidx;" NL "}";
3000         m_program = CreateProgramCS(glsl_cs);
3001         glLinkProgram(m_program);
3002         if (!CheckProgram(m_program))
3003             return ERROR;
3004 
3005         glGenBuffers(2, m_storage_buffer);
3006         /* counter buffer */
3007         {
3008             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
3009             glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3010             int *ptr = reinterpret_cast<int *>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
3011             if (!ptr)
3012                 return ERROR;
3013             *ptr++ = 0;
3014             *ptr++ = 7;
3015             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3016         }
3017         /* output buffer */
3018         {
3019             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
3020             glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3021         }
3022         glUseProgram(m_program);
3023         glDispatchCompute(1, 1, 1);
3024         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3025 
3026         GLuint *udata = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
3027         if (!udata)
3028             return ERROR;
3029         for (GLuint i = 0; i < 8; ++i)
3030         {
3031             if (udata[i] != i)
3032             {
3033                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
3034                                                     << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
3035                 return ERROR;
3036             }
3037         }
3038         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3039         GLint *idata = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
3040         if (!idata)
3041             return ERROR;
3042         for (GLint i = 0; i < 8; ++i)
3043         {
3044             if (idata[i] != i)
3045             {
3046                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
3047                                                     << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
3048                 return ERROR;
3049             }
3050         }
3051         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3052         return NO_ERROR;
3053     }
3054 
Cleanup()3055     virtual long Cleanup()
3056     {
3057         glUseProgram(0);
3058         glDeleteProgram(m_program);
3059         glDeleteBuffers(2, m_storage_buffer);
3060         return NO_ERROR;
3061     }
3062 };
3063 //-----------------------------------------------------------------------------
3064 // 1.9.x BasicStdLayoutBase2
3065 //-----------------------------------------------------------------------------
3066 
3067 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
3068 {
3069     GLuint m_program;
3070     GLuint m_buffer[8];
3071     GLuint m_vertex_array;
3072 
3073     virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
3074 
Setup()3075     virtual long Setup()
3076     {
3077         m_program = 0;
3078         memset(m_buffer, 0, sizeof(m_buffer));
3079         m_vertex_array = 0;
3080         return NO_ERROR;
3081     }
3082 
Run()3083     virtual long Run()
3084     {
3085         if (!SupportedInVS(8))
3086             return NOT_SUPPORTED;
3087         std::vector<GLubyte> in_data[4];
3088         const char *glsl_vs = GetInput(in_data);
3089 
3090         m_program = CreateProgram(glsl_vs, "");
3091         glLinkProgram(m_program);
3092         if (!CheckProgram(m_program))
3093             return ERROR;
3094 
3095         glGenBuffers(8, m_buffer);
3096 
3097         for (GLuint i = 0; i < 4; ++i)
3098         {
3099             // input buffers
3100             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3101             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3102 
3103             // output buffers
3104             std::vector<GLubyte> out_data(in_data[i].size());
3105             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3106             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3107         }
3108 
3109         glGenVertexArrays(1, &m_vertex_array);
3110         glEnable(GL_RASTERIZER_DISCARD);
3111 
3112         glUseProgram(m_program);
3113         glBindVertexArray(m_vertex_array);
3114         glDrawArrays(GL_POINTS, 0, 1);
3115 
3116         bool status = true;
3117         for (int j = 0; j < 4; ++j)
3118         {
3119             std::vector<GLubyte> out_data(in_data[j].size());
3120             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3121             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3122             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
3123 
3124             for (size_t i = 0; i < in_data[j].size(); ++i)
3125             {
3126                 if (in_data[j][i] != out_data[i])
3127                 {
3128                     m_context.getTestContext().getLog()
3129                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3130                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3131                         << tcu::TestLog::EndMessage;
3132                     status = false;
3133                 }
3134             }
3135         }
3136         if (!status)
3137             return ERROR;
3138         return NO_ERROR;
3139     }
3140 
Cleanup()3141     virtual long Cleanup()
3142     {
3143         glDisable(GL_RASTERIZER_DISCARD);
3144         glUseProgram(0);
3145         glDeleteProgram(m_program);
3146         glDeleteBuffers(8, m_buffer);
3147         glDeleteVertexArrays(1, &m_vertex_array);
3148         return NO_ERROR;
3149     }
3150 };
3151 
3152 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
3153 {
3154     GLuint m_program;
3155     GLuint m_buffer[8];
3156 
3157     virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
3158 
Setup()3159     virtual long Setup()
3160     {
3161         m_program = 0;
3162         memset(m_buffer, 0, sizeof(m_buffer));
3163         return NO_ERROR;
3164     }
3165 
Run()3166     virtual long Run()
3167     {
3168         std::vector<GLubyte> in_data[4];
3169         std::stringstream ss;
3170         GLint blocksCS;
3171         glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
3172         if (blocksCS < 8)
3173             return NO_ERROR;
3174         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
3175         m_program = CreateProgramCS(ss.str());
3176         glLinkProgram(m_program);
3177         if (!CheckProgram(m_program))
3178             return ERROR;
3179 
3180         glGenBuffers(8, m_buffer);
3181 
3182         for (GLuint i = 0; i < 4; ++i)
3183         {
3184             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3185             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3186 
3187             std::vector<GLubyte> out_data(in_data[i].size());
3188             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3189             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3190         }
3191 
3192         glUseProgram(m_program);
3193         glDispatchCompute(1, 1, 1);
3194         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3195 
3196         bool status = true;
3197         for (int j = 0; j < 4; ++j)
3198         {
3199             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3200             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
3201                                                             GL_MAP_READ_BIT);
3202             if (!out_data)
3203                 return ERROR;
3204 
3205             for (size_t i = 0; i < in_data[j].size(); ++i)
3206             {
3207                 if (in_data[j][i] != out_data[i])
3208                 {
3209                     m_context.getTestContext().getLog()
3210                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3211                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3212                         << tcu::TestLog::EndMessage;
3213                     status = false;
3214                 }
3215             }
3216             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3217         }
3218         if (!status)
3219             return ERROR;
3220         return NO_ERROR;
3221     }
3222 
Cleanup()3223     virtual long Cleanup()
3224     {
3225         glUseProgram(0);
3226         glDeleteProgram(m_program);
3227         glDeleteBuffers(8, m_buffer);
3228         return NO_ERROR;
3229     }
3230 };
3231 //-----------------------------------------------------------------------------
3232 // 1.9.1 BasicStdLayoutCase1
3233 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])3234 const char *GetInputC1(std::vector<GLubyte> in_data[4])
3235 {
3236     for (int i = 0; i < 4; ++i)
3237     {
3238         in_data[i].resize(1 * 4);
3239         float *fp = reinterpret_cast<float *>(&in_data[i][0]);
3240         fp[0]     = static_cast<float>(i + 1) * 1.0f;
3241     }
3242 
3243     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
3244               "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
3245               "void main() {" NL "  for (int i = 0; i < 4; ++i) {" NL "    g_output[i].data0 = g_input[i].data0;" NL
3246               "  }" NL "}";
3247 }
3248 
3249 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3250 {
GetInput(std::vector<GLubyte> in_data[4])3251     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3252     {
3253         return GetInputC1(in_data);
3254     }
3255 };
3256 
3257 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3258 {
GetInput(std::vector<GLubyte> in_data[4])3259     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3260     {
3261         return GetInputC1(in_data);
3262     }
3263 };
3264 
3265 //-----------------------------------------------------------------------------
3266 // 1.9.2 BasicStdLayoutCase2
3267 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3268 const char *GetInputC2(std::vector<GLubyte> in_data[4])
3269 {
3270     /* input 0, std140 */
3271     {
3272         in_data[0].resize(12 * 4);
3273         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3274         fp[0]     = 1.0f;
3275         fp[1]     = 0.0f;
3276         fp[2]     = 0.0f;
3277         fp[3]     = 0.0f;
3278         fp[4]     = 2.0f;
3279         fp[5]     = 0.0f;
3280         fp[6]     = 0.0f;
3281         fp[7]     = 0.0f;
3282         fp[8]     = 3.0f;
3283         fp[9]     = 0.0f;
3284         fp[10]    = 0.0f;
3285         fp[11]    = 0.0f;
3286     }
3287     /* input 1, std430 */
3288     {
3289         in_data[1].resize(3 * 4);
3290         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3291         fp[0]     = 4.0f;
3292         fp[1]     = 5.0f;
3293         fp[2]     = 6.0f;
3294     }
3295     /* input 2, std140 */
3296     {
3297         in_data[2].resize(12 * 4);
3298         float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3299         fp[0]     = 7.0f;
3300         fp[1]     = 0.0f;
3301         fp[2]     = 0.0f;
3302         fp[3]     = 0.0f;
3303         fp[4]     = 8.0f;
3304         fp[5]     = 0.0f;
3305         fp[6]     = 0.0f;
3306         fp[7]     = 0.0f;
3307         fp[8]     = 9.0f;
3308         fp[9]     = 0.0f;
3309         fp[10]    = 0.0f;
3310         fp[11]    = 0.0f;
3311     }
3312     /* input 3, std430 */
3313     {
3314         in_data[3].resize(3 * 4);
3315         float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3316         fp[0]     = 10.0f;
3317         fp[1]     = 11.0f;
3318         fp[2]     = 12.0f;
3319     }
3320     return NL "layout(std140, binding = 0) buffer Input0 {" NL "  float data0[3];" NL "} g_input0;" NL
3321               "layout(std430, binding = 1) buffer Input1 {" NL "  float data0[3];" NL "} g_input1;" NL
3322               "layout(std140, binding = 2) buffer Input2 {" NL "  float data0[3];" NL "} g_input2;" NL
3323               "layout(std430, binding = 3) buffer Input3 {" NL "  float data0[3];" NL "} g_input3;" NL
3324               "layout(std140, binding = 4) buffer Output0 {" NL "  float data0[3];" NL "} g_output0;" NL
3325               "layout(std430, binding = 5) buffer Output1 {" NL "  float data0[3];" NL "} g_output1;" NL
3326               "layout(std140, binding = 6) buffer Output2 {" NL "  float data0[3];" NL "} g_output2;" NL
3327               "layout(std430, binding = 7) buffer Output3 {" NL "  float data0[3];" NL "} g_output3;" NL
3328               "void main() {" NL
3329               "  for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3330               "  for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3331               "  for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3332               "  for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3333 }
3334 
3335 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3336 {
GetInput(std::vector<GLubyte> in_data[4])3337     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3338     {
3339         return GetInputC2(in_data);
3340     }
3341 };
3342 
3343 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3344 {
GetInput(std::vector<GLubyte> in_data[4])3345     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3346     {
3347         return GetInputC2(in_data);
3348     }
3349 };
3350 
3351 //-----------------------------------------------------------------------------
3352 // 1.9.3 BasicStdLayoutCase3
3353 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3354 const char *GetInputC3(std::vector<GLubyte> in_data[4])
3355 {
3356     /* input 0, std140 */
3357     {
3358         in_data[0].resize(62 * 4);
3359         float *fp                            = reinterpret_cast<float *>(&in_data[0][0]);
3360         int *ip                              = reinterpret_cast<int *>(&in_data[0][0]);
3361         ip[0]                                = 1;
3362         ip[1]                                = 0;
3363         ip[2]                                = 0;
3364         ip[3]                                = 0;
3365         fp[4]                                = 2.0f;
3366         fp[5]                                = 0.0f;
3367         fp[6]                                = 0.0f;
3368         fp[7]                                = 0.0f;
3369         fp[8]                                = 3.0f;
3370         fp[9]                                = 0.0f;
3371         fp[10]                               = 0.0f;
3372         fp[11]                               = 0.0f;
3373         fp[12]                               = 4.0f;
3374         fp[13]                               = 0.0f;
3375         fp[14]                               = 0.0f;
3376         fp[15]                               = 0.0f;
3377         fp[16]                               = 5.0f;
3378         fp[17]                               = 0.0f;
3379         fp[18]                               = 0.0f;
3380         fp[19]                               = 0.0f;
3381         fp[20]                               = 6.0f;
3382         fp[21]                               = 0.0f;
3383         fp[22]                               = 0.0f;
3384         fp[23]                               = 0.0f;
3385         fp[24]                               = 7.0f;
3386         fp[25]                               = 8.0f;
3387         fp[26]                               = 0.0f;
3388         fp[27]                               = 0.0f;
3389         fp[28]                               = 9.0f;
3390         fp[29]                               = 10.0f;
3391         fp[30]                               = 0.0f;
3392         fp[31]                               = 0.0f;
3393         fp[32]                               = 11.0f;
3394         fp[33]                               = 12.0f;
3395         fp[34]                               = 0.0f;
3396         fp[35]                               = 0.0f;
3397         *reinterpret_cast<double *>(fp + 36) = 13.0;
3398         *reinterpret_cast<double *>(fp + 38) = 0.0;
3399         *reinterpret_cast<double *>(fp + 40) = 14.0;
3400         *reinterpret_cast<double *>(fp + 42) = 0.0;
3401         *reinterpret_cast<double *>(fp + 44) = 15.0;
3402         *reinterpret_cast<double *>(fp + 46) = 0.0;
3403         ip[48]                               = 16;
3404         ip[49]                               = 0;
3405         ip[50]                               = 0;
3406         ip[51]                               = 0;
3407         ip[52]                               = 0;
3408         ip[53]                               = 0;
3409         ip[54]                               = 0;
3410         ip[55]                               = 0;
3411         *reinterpret_cast<double *>(fp + 56) = 17.0;
3412         *reinterpret_cast<double *>(fp + 58) = 18.0;
3413         *reinterpret_cast<double *>(fp + 60) = 19.0;
3414     }
3415     /* input 1, std430 */
3416     {
3417         in_data[1].resize(32 * 4);
3418         float *fp                            = reinterpret_cast<float *>(&in_data[1][0]);
3419         int *ip                              = reinterpret_cast<int *>(&in_data[1][0]);
3420         ip[0]                                = 1;
3421         fp[1]                                = 2.0f;
3422         fp[2]                                = 3.0f;
3423         fp[3]                                = 4.0f;
3424         fp[4]                                = 5.0f;
3425         fp[5]                                = 6.0f;
3426         fp[6]                                = 7.0f;
3427         fp[7]                                = 8.0f;
3428         fp[8]                                = 9.0f;
3429         fp[9]                                = 10.0f;
3430         fp[10]                               = 11.0f;
3431         fp[11]                               = 12.0f;
3432         *reinterpret_cast<double *>(fp + 12) = 13.0;
3433         *reinterpret_cast<double *>(fp + 14) = 14.0;
3434         *reinterpret_cast<double *>(fp + 16) = 15.0;
3435         ip[18]                               = 16;
3436         ip[19]                               = 0;
3437         *reinterpret_cast<double *>(fp + 20) = 0.0;
3438         *reinterpret_cast<double *>(fp + 22) = 0.0;
3439         *reinterpret_cast<double *>(fp + 24) = 17.0;
3440         *reinterpret_cast<double *>(fp + 26) = 18.0;
3441         *reinterpret_cast<double *>(fp + 28) = 19.0;
3442     }
3443     /* input 2, std140 */
3444     {
3445         in_data[2].resize(5 * 4);
3446         int *ip = reinterpret_cast<int *>(&in_data[2][0]);
3447         ip[0]   = 1;
3448         ip[1]   = 0;
3449         ip[2]   = 0;
3450         ip[3]   = 0;
3451         ip[4]   = 2;
3452     }
3453     /* input 3, std430 */
3454     {
3455         in_data[3].resize(2 * 4);
3456         int *ip = reinterpret_cast<int *>(&in_data[3][0]);
3457         ip[0]   = 1;
3458         ip[1]   = 2;
3459     }
3460     return NL "layout(std140, binding = 0) buffer Input0 {" NL "  int data0;" NL "  float data1[5];" NL
3461               "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3462               "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL "  int data0;" NL "  float data1[5];" NL
3463               "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3464               "} g_input1;" NL "struct Struct0 {" NL "  int data0;" NL "};" NL
3465               "layout(std140, binding = 2) buffer Input2 {" NL "  int data0;" NL "  Struct0 data1;" NL "} g_input2;" NL
3466               "layout(std430, binding = 3) buffer Input3 {" NL "  int data0;" NL "  Struct0 data1;" NL "} g_input3;"
3467 
3468         NL "layout(std140, binding = 4) buffer Output0 {" NL "  int data0;" NL "  float data1[5];" NL
3469               "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3470               "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL "  int data0;" NL
3471               "  float data1[5];" NL "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL
3472               "  dvec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL "  int data0;" NL
3473               "  Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3474               "  int data0;" NL "  Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3475               "  g_output0.data0 = g_input0.data0;" NL
3476               "  for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3477               "  g_output0.data2 = g_input0.data2;" NL "  g_output0.data3 = g_input0.data3;" NL
3478               "  for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3479               "  g_output0.data5 = g_input0.data5;" NL "  g_output0.data6 = g_input0.data6;"
3480 
3481         NL "  g_output1.data0 = g_input1.data0;" NL
3482               "  for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3483               "  g_output1.data2 = g_input1.data2;" NL "  g_output1.data3 = g_input1.data3;" NL
3484               "  for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3485               "  g_output1.data5 = g_input1.data5;" NL "  g_output1.data6 = g_input1.data6;"
3486 
3487         NL "  g_output2.data0 = g_input2.data0;" NL "  g_output2.data1 = g_input2.data1;"
3488 
3489         NL "  g_output3.data0 = g_input3.data0;" NL "  g_output3.data1 = g_input3.data1;" NL "}";
3490 }
3491 
3492 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3493 {
GetInput(std::vector<GLubyte> in_data[4])3494     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3495     {
3496         return GetInputC3(in_data);
3497     }
3498 };
3499 
3500 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3501 {
GetInput(std::vector<GLubyte> in_data[4])3502     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3503     {
3504         return GetInputC3(in_data);
3505     }
3506 };
3507 
3508 //-----------------------------------------------------------------------------
3509 // 1.9.4 BasicStdLayoutCase4
3510 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3511 const char *GetInputC4(std::vector<GLubyte> in_data[4])
3512 {
3513     /* input 0, std140 */
3514     {
3515         in_data[0].resize(60 * 4);
3516         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3517         int *ip   = reinterpret_cast<int *>(&in_data[0][0]);
3518         ip[0]     = 1;
3519         ip[1]     = 0;
3520         ip[2]     = 0;
3521         ip[3]     = 0;
3522         ip[4]     = 2;
3523         ip[5]     = 3;
3524         ip[6]     = 0;
3525         ip[7]     = 0;
3526         ip[8]     = 4;
3527         ip[9]     = 5;
3528         ip[10]    = 0;
3529         ip[11]    = 0;
3530         fp[12]    = 6.0f;
3531         fp[13]    = 0.0f;
3532         fp[14]    = 0.0f;
3533         fp[15]    = 0.0f;
3534         fp[16]    = 7.0f;
3535         fp[17]    = 8.0f;
3536         fp[18]    = 0.0f;
3537         fp[19]    = 0.0f;
3538         ip[20]    = 9;
3539         ip[21]    = 10;
3540         ip[22]    = 11;
3541         ip[23]    = 0;
3542         fp[24]    = 12.0f;
3543         fp[25]    = 13.0f;
3544         fp[26]    = 0.0f;
3545         fp[27]    = 0.0f;
3546         ip[28]    = 14;
3547         ip[29]    = 15;
3548         ip[30]    = 16;
3549         ip[31]    = 0;
3550         fp[32]    = 17.0f;
3551         fp[33]    = 0.0f;
3552         fp[34]    = 0.0f;
3553         fp[35]    = 0.0f;
3554         ip[36]    = 18;
3555         ip[37]    = 0;
3556         ip[38]    = 0;
3557         ip[39]    = 0;
3558         ip[40]    = 19;
3559         ip[41]    = 20;
3560         ip[42]    = 0;
3561         ip[43]    = 0;
3562         ip[44]    = 21;
3563         ip[45]    = 0;
3564         ip[45]    = 0;
3565         ip[45]    = 0;
3566         fp[48]    = 22.0f;
3567         fp[49]    = 23.0f;
3568         fp[50]    = 0.0f;
3569         fp[51]    = 0.0f;
3570         ip[52]    = 24;
3571         ip[53]    = 25;
3572         ip[54]    = 26;
3573         ip[55]    = 0;
3574         fp[56]    = 27.0f;
3575     }
3576     /* input 1, std140 */
3577     {
3578         in_data[1].resize(60 * 4);
3579         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3580         int *ip   = reinterpret_cast<int *>(&in_data[1][0]);
3581         ip[0]     = 101;
3582         ip[1]     = 0;
3583         ip[2]     = 0;
3584         ip[3]     = 0;
3585         ip[4]     = 102;
3586         ip[5]     = 103;
3587         ip[6]     = 0;
3588         ip[7]     = 0;
3589         ip[8]     = 104;
3590         ip[9]     = 105;
3591         ip[10]    = 0;
3592         ip[11]    = 0;
3593         fp[12]    = 106.0f;
3594         fp[13]    = 0.0f;
3595         fp[14]    = 0.0f;
3596         fp[15]    = 0.0f;
3597         fp[16]    = 107.0f;
3598         fp[17]    = 108.0f;
3599         fp[18]    = 0.0f;
3600         fp[19]    = 0.0f;
3601         ip[20]    = 109;
3602         ip[21]    = 110;
3603         ip[22]    = 111;
3604         ip[23]    = 0;
3605         fp[24]    = 112.0f;
3606         fp[25]    = 113.0f;
3607         fp[26]    = 0.0f;
3608         fp[27]    = 0.0f;
3609         ip[28]    = 114;
3610         ip[29]    = 115;
3611         ip[30]    = 116;
3612         ip[31]    = 0;
3613         fp[32]    = 117.0f;
3614         fp[33]    = 0.0f;
3615         fp[34]    = 0.0f;
3616         fp[35]    = 0.0f;
3617         ip[36]    = 118;
3618         ip[37]    = 0;
3619         ip[38]    = 0;
3620         ip[39]    = 0;
3621         ip[40]    = 119;
3622         ip[41]    = 120;
3623         ip[42]    = 0;
3624         ip[43]    = 0;
3625         ip[44]    = 121;
3626         ip[45]    = 0;
3627         ip[45]    = 0;
3628         ip[45]    = 0;
3629         fp[48]    = 122.0f;
3630         fp[49]    = 123.0f;
3631         fp[50]    = 0.0f;
3632         fp[51]    = 0.0f;
3633         ip[52]    = 124;
3634         ip[53]    = 125;
3635         ip[54]    = 126;
3636         ip[55]    = 0;
3637         fp[56]    = 127.0f;
3638     }
3639     /* input 2, std430 */
3640     {
3641         in_data[2].resize(48 * 4);
3642         float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3643         int *ip   = reinterpret_cast<int *>(&in_data[2][0]);
3644         ip[0]     = 1000;
3645         ip[1]     = 0;
3646         ip[2]     = 1001;
3647         ip[3]     = 1002;
3648         ip[4]     = 1003;
3649         ip[5]     = 1004;
3650         fp[6]     = 1005.0f;
3651         fp[7]     = 0.0f;
3652         fp[8]     = 1006.0f;
3653         fp[9]     = 1007.0f;
3654         fp[10]    = 0.0f;
3655         fp[11]    = 0.0f;
3656         ip[12]    = 1008;
3657         ip[13]    = 1009;
3658         ip[14]    = 1010;
3659         ip[15]    = 0;
3660         fp[16]    = 1011.0f;
3661         fp[17]    = 1012.0f;
3662         fp[18]    = 0.0f;
3663         fp[19]    = 0.0f;
3664         ip[20]    = 1013;
3665         ip[21]    = 1014;
3666         ip[22]    = 1015;
3667         ip[23]    = 0;
3668         fp[24]    = 1016.0f;
3669         fp[25]    = 0.0f;
3670         fp[26]    = 0.0f;
3671         fp[27]    = 0.0f;
3672         ip[28]    = 1017;
3673         ip[29]    = 0;
3674         ip[30]    = 1018;
3675         ip[31]    = 1019;
3676         ip[32]    = 1020;
3677         ip[33]    = 0;
3678         ip[34]    = 0;
3679         ip[35]    = 0;
3680         fp[36]    = 1021.0f;
3681         fp[37]    = 1022.0f;
3682         fp[38]    = 0.0f;
3683         fp[39]    = 0.0f;
3684         ip[40]    = 1023;
3685         ip[41]    = 1024;
3686         ip[42]    = 1025;
3687         ip[43]    = 0;
3688         fp[44]    = 1026.0f;
3689     }
3690     /* input 3, std430 */
3691     {
3692         in_data[3].resize(48 * 4);
3693         float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3694         int *ip   = reinterpret_cast<int *>(&in_data[3][0]);
3695         ip[0]     = 10000;
3696         ip[1]     = 0;
3697         ip[2]     = 10001;
3698         ip[3]     = 10002;
3699         ip[4]     = 10003;
3700         ip[5]     = 10004;
3701         fp[6]     = 10005.0f;
3702         fp[7]     = 0.0f;
3703         fp[8]     = 10006.0f;
3704         fp[9]     = 10007.0f;
3705         fp[10]    = 0.0f;
3706         fp[11]    = 0.0f;
3707         ip[12]    = 10008;
3708         ip[13]    = 10009;
3709         ip[14]    = 10010;
3710         ip[15]    = 0;
3711         fp[16]    = 10011.0f;
3712         fp[17]    = 10012.0f;
3713         fp[18]    = 0.0f;
3714         fp[19]    = 0.0f;
3715         ip[20]    = 10013;
3716         ip[21]    = 10014;
3717         ip[22]    = 10015;
3718         ip[23]    = 0;
3719         fp[24]    = 10016.0f;
3720         fp[25]    = 0.0f;
3721         fp[26]    = 0.0f;
3722         fp[27]    = 0.0f;
3723         ip[28]    = 10017;
3724         ip[29]    = 0;
3725         ip[30]    = 10018;
3726         ip[31]    = 10019;
3727         ip[32]    = 10020;
3728         ip[33]    = 0;
3729         ip[34]    = 0;
3730         ip[35]    = 0;
3731         fp[36]    = 10021.0f;
3732         fp[37]    = 10022.0f;
3733         fp[38]    = 0.0f;
3734         fp[39]    = 0.0f;
3735         ip[40]    = 10023;
3736         ip[41]    = 10024;
3737         ip[42]    = 10025;
3738         ip[43]    = 0;
3739         fp[44]    = 10026.0f;
3740     }
3741     return NL
3742         "struct Struct0 {" NL "  ivec2 data0;" NL "};" NL "struct Struct1 {" NL "  vec2 data0;" NL "  ivec3 data1;" NL
3743         "};" NL "struct Struct2 {" NL "  int data0;" NL "  Struct0 data1;" NL "  int data2;" NL "  Struct1 data3;" NL
3744         "  float data4;" NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL "  int data0;" NL
3745         "  Struct0 data1[2];" NL "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL
3746         "} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL "  int data0;" NL
3747         "  Struct0 data1[2];" NL "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL
3748         "} g_input23[2];"
3749 
3750         NL "layout(std140, binding = 4) buffer Output01 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3751         "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output01[2];" NL
3752         "layout(std430, binding = 6) buffer Output23 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3753         "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output23[2];" NL NL
3754         "void main() {" NL "  for (int b = 0; b < g_input01.length(); ++b) {" NL
3755         "    g_output01[b].data0 = g_input01[b].data0;" NL
3756         "    for (int i = 0; i < g_input01[b].data1.length(); ++i) g_output01[b].data1[i] = g_input01[b].data1[i];" NL
3757         "    g_output01[b].data2 = g_input01[b].data2;" NL "    g_output01[b].data3[0] = g_input01[b].data3[0];" NL
3758         "    g_output01[b].data3[1] = g_input01[b].data3[1];" NL "    g_output01[b].data4 = g_input01[b].data4;" NL
3759         "  }" NL "  g_output01[0].data5 = g_input01[0].data5;" NL "  g_output01[1].data5 = g_input01[1].data5;" NL NL
3760         "  for (int b = 0; b < g_input23.length(); ++b) {" NL "    g_output23[b].data0 = g_input23[b].data0;" NL
3761         "    for (int i = 0; i < g_input23[b].data1.length(); ++i) g_output23[b].data1[i] = g_input23[b].data1[i];" NL
3762         "    g_output23[b].data2 = g_input23[b].data2;" NL "    g_output23[b].data3[0] = g_input23[b].data3[0];" NL
3763         "    g_output23[b].data3[1] = g_input23[b].data3[1];" NL "    g_output23[b].data4 = g_input23[b].data4;" NL
3764         "  }" NL "  g_output23[0].data5 = g_input23[0].data5;" NL "  g_output23[1].data5 = g_input23[1].data5;" NL "}";
3765 }
3766 
3767 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3768 {
GetInput(std::vector<GLubyte> in_data[4])3769     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3770     {
3771         return GetInputC4(in_data);
3772     }
3773 };
3774 
3775 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3776 {
GetInput(std::vector<GLubyte> in_data[4])3777     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3778     {
3779         return GetInputC4(in_data);
3780     }
3781 };
3782 //-----------------------------------------------------------------------------
3783 // 1.10.x BasicOperationsBase
3784 //-----------------------------------------------------------------------------
3785 
3786 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3787 {
3788     GLuint m_program;
3789     GLuint m_buffer[2];
3790     GLuint m_vertex_array;
3791 
3792     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3793 
Setup()3794     virtual long Setup()
3795     {
3796         m_program = 0;
3797         memset(m_buffer, 0, sizeof(m_buffer));
3798         m_vertex_array = 0;
3799         return NO_ERROR;
3800     }
3801 
Run()3802     virtual long Run()
3803     {
3804         if (!SupportedInVS(2))
3805             return NOT_SUPPORTED;
3806         std::vector<GLubyte> in_data;
3807         std::vector<GLubyte> expected_data;
3808         const char *glsl_vs = GetInput(in_data, expected_data);
3809 
3810         m_program = CreateProgram(glsl_vs, "");
3811         glLinkProgram(m_program);
3812         if (!CheckProgram(m_program))
3813             return ERROR;
3814 
3815         glGenBuffers(2, m_buffer);
3816 
3817         /* output buffer */
3818         {
3819             std::vector<GLubyte> zero(expected_data.size());
3820             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3821             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3822         }
3823         // input buffer
3824         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3825         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3826 
3827         glGenVertexArrays(1, &m_vertex_array);
3828         glEnable(GL_RASTERIZER_DISCARD);
3829 
3830         glUseProgram(m_program);
3831         glBindVertexArray(m_vertex_array);
3832         glDrawArrays(GL_POINTS, 0, 1);
3833 
3834         std::vector<GLubyte> out_data(expected_data.size());
3835         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3836         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3837         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)out_data.size(), &out_data[0]);
3838 
3839         bool status = true;
3840         for (size_t i = 0; i < out_data.size(); ++i)
3841         {
3842             if (expected_data[i] != out_data[i])
3843             {
3844                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3845                                                     << " is " << tcu::toHex(out_data[i]) << " should be "
3846                                                     << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3847                 status = false;
3848             }
3849         }
3850         if (!status)
3851             return ERROR;
3852         return NO_ERROR;
3853     }
3854 
Cleanup()3855     virtual long Cleanup()
3856     {
3857         glDisable(GL_RASTERIZER_DISCARD);
3858         glUseProgram(0);
3859         glDeleteProgram(m_program);
3860         glDeleteBuffers(2, m_buffer);
3861         glDeleteVertexArrays(1, &m_vertex_array);
3862         return NO_ERROR;
3863     }
3864 };
3865 
3866 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3867 {
3868     GLuint m_program;
3869     GLuint m_buffer[2];
3870 
3871     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3872 
Setup()3873     virtual long Setup()
3874     {
3875         m_program = 0;
3876         memset(m_buffer, 0, sizeof(m_buffer));
3877         return NO_ERROR;
3878     }
3879 
Run()3880     virtual long Run()
3881     {
3882         std::vector<GLubyte> in_data;
3883         std::vector<GLubyte> expected_data;
3884 
3885         std::stringstream ss;
3886         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data, expected_data);
3887         m_program = CreateProgramCS(ss.str());
3888         glLinkProgram(m_program);
3889         if (!CheckProgram(m_program))
3890             return ERROR;
3891 
3892         glGenBuffers(2, m_buffer);
3893 
3894         /* output buffer */
3895         {
3896             std::vector<GLubyte> zero(expected_data.size());
3897             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3898             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3899         }
3900         // input buffer
3901         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3902         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3903 
3904         glUseProgram(m_program);
3905         glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3906         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3907         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3908         glDispatchCompute(1, 1, 1);
3909 
3910         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3911         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3912         GLubyte *out_data =
3913             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3914         if (!out_data)
3915             return ERROR;
3916 
3917         bool status = true;
3918         for (size_t i = 0; i < expected_data.size(); ++i)
3919         {
3920             if (expected_data[i] != out_data[i])
3921             {
3922                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3923                                                     << " is " << tcu::toHex(out_data[i]) << " should be "
3924                                                     << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3925                 status = false;
3926             }
3927         }
3928         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3929         if (!status)
3930             return ERROR;
3931         return NO_ERROR;
3932     }
3933 
Cleanup()3934     virtual long Cleanup()
3935     {
3936         glUseProgram(0);
3937         glDeleteProgram(m_program);
3938         glDeleteBuffers(2, m_buffer);
3939         return NO_ERROR;
3940     }
3941 };
3942 
3943 //-----------------------------------------------------------------------------
3944 // 1.10.1 BasicOperationsCase1
3945 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946 const char *GetInputOp1(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3947 {
3948     /* input */
3949     {
3950         in_data.resize(16 * 9);
3951         int *ip   = reinterpret_cast<int *>(&in_data[0]);
3952         float *fp = reinterpret_cast<float *>(&in_data[0]);
3953         ip[0]     = 1;
3954         ip[1]     = 2;
3955         ip[2]     = 3;
3956         ip[3]     = 4;
3957         fp[4]     = 1.0f;
3958         fp[5]     = 2.0f;
3959         fp[6]     = 3.0f;
3960         fp[7]     = 0.0f;
3961         ip[8]     = 1;
3962         ip[9]     = 2;
3963         ip[10]    = 3;
3964         ip[11]    = 4;
3965         ip[12]    = 1;
3966         ip[13]    = -2;
3967         ip[14]    = 3;
3968         ip[15]    = 4;
3969         fp[16]    = 1.0f;
3970         fp[17]    = 2.0f;
3971         fp[18]    = 3.0f;
3972         fp[19]    = 4.0f;
3973         fp[20]    = 1.0f;
3974         fp[21]    = 2.0f;
3975         fp[22]    = 3.0f;
3976         fp[23]    = 4.0f;
3977         fp[24]    = 1.0f;
3978         fp[25]    = 2.0f;
3979         fp[26]    = 3.0f;
3980         fp[27]    = 4.0f;
3981         fp[28]    = 1.0f;
3982         fp[29]    = 2.0f;
3983         fp[30]    = 3.0f;
3984         fp[31]    = 4.0f;
3985         fp[32]    = 1.0f;
3986         fp[33]    = 0.0f;
3987         fp[34]    = 0.0f;
3988         fp[35]    = 4.0f;
3989     }
3990     /* expected output */
3991     {
3992         out_data.resize(16 * 9);
3993         int *ip   = reinterpret_cast<int *>(&out_data[0]);
3994         float *fp = reinterpret_cast<float *>(&out_data[0]);
3995         ip[0]     = 4;
3996         ip[1]     = 3;
3997         ip[2]     = 2;
3998         ip[3]     = 1;
3999         fp[4]     = 3.0f;
4000         fp[5]     = 2.0f;
4001         fp[6]     = 1.0f;
4002         fp[7]     = 0.0f;
4003         ip[8]     = 4;
4004         ip[9]     = 1;
4005         ip[10]    = 0;
4006         ip[11]    = 3;
4007         ip[12]    = 10;
4008         ip[13]    = 4;
4009         ip[14]    = -2;
4010         ip[15]    = 20;
4011         fp[16]    = 50.0f;
4012         fp[17]    = 5.0f;
4013         fp[18]    = 2.0f;
4014         fp[19]    = 30.0f;
4015         fp[20]    = 4.0f;
4016         fp[21]    = 2.0f;
4017         fp[22]    = 3.0f;
4018         fp[23]    = 1.0f;
4019         fp[24]    = 4.0f;
4020         fp[25]    = 3.0f;
4021         fp[26]    = 2.0f;
4022         fp[27]    = 1.0f;
4023         fp[28]    = 2.0f;
4024         fp[29]    = 2.0f;
4025         fp[30]    = 2.0f;
4026         fp[31]    = 2.0f;
4027         fp[32]    = 4.0f;
4028         fp[33]    = 0.0f;
4029         fp[34]    = 0.0f;
4030         fp[35]    = 1.0f;
4031     }
4032     return NL "layout(std430, binding = 0) buffer Input {" NL "  ivec4 data0;" NL "  vec3 data1;" NL "  uvec4 data2;" NL
4033               "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_input;" NL
4034               "layout(std430, binding = 1) buffer Output {" NL "  ivec4 data0;" NL "  vec3 data1;" NL
4035               "  uvec4 data2;" NL "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_output;" NL
4036               "uniform vec3 g_value0 = vec3(10, 20, 30);" NL "uniform int g_index1 = 1;" NL "void main() {" NL
4037               "  int index0 = 0;" NL "  g_output.data0.wzyx = g_input.data0;" NL
4038               "  g_output.data1 = g_input.data1.zyx;" NL "  g_output.data2.xwy = g_input.data2.wzx;" NL
4039               "  g_output.data3.xw = ivec2(10, 20);" NL "  g_output.data3.zy = g_input.data3.yw;" NL
4040               "  g_output.data4.wx = g_value0.xz;" NL "  g_output.data4.wx += g_value0.yy;" NL
4041               "  g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;" NL
4042               "  g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
4043               "  g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
4044               "  g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
4045               "  g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
4046 }
4047 
4048 class BasicOperationsCase1VS : public BasicOperationsBaseVS
4049 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4050     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4051     {
4052         return GetInputOp1(in_data, out_data);
4053     }
4054 };
4055 
4056 class BasicOperationsCase1CS : public BasicOperationsBaseCS
4057 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4058     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4059     {
4060         return GetInputOp1(in_data, out_data);
4061     }
4062 };
4063 //-----------------------------------------------------------------------------
4064 // 1.10.2 BasicOperationsCase2
4065 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4066 const char *GetInputOp2(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4067 {
4068     /* input */
4069     {
4070         in_data.resize(16 * 8);
4071         float *fp = reinterpret_cast<float *>(&in_data[0]);
4072         fp[0]     = 1.0f;
4073         fp[1]     = 0.0f;
4074         fp[2]     = 0.0f;
4075         fp[3]     = 0.0f;
4076         fp[4]     = 0.0f;
4077         fp[5]     = 1.0f;
4078         fp[6]     = 0.0f;
4079         fp[7]     = 0.0f;
4080         fp[8]     = 0.0f;
4081         fp[9]     = 0.0f;
4082         fp[10]    = 1.0f;
4083         fp[11]    = 0.0f;
4084         fp[12]    = 0.0f;
4085         fp[13]    = 0.0f;
4086         fp[14]    = 0.0f;
4087         fp[15]    = 1.0f;
4088 
4089         fp[16] = 2.0f;
4090         fp[17] = 0.0f;
4091         fp[18] = 0.0f;
4092         fp[19] = 0.0f;
4093         fp[20] = 0.0f;
4094         fp[21] = 3.0f;
4095         fp[22] = 0.0f;
4096         fp[23] = 0.0f;
4097         fp[24] = 0.0f;
4098         fp[25] = 0.0f;
4099         fp[26] = 4.0f;
4100         fp[27] = 0.0f;
4101         fp[28] = 0.0f;
4102         fp[29] = 0.0f;
4103         fp[30] = 0.0f;
4104         fp[31] = 5.0f;
4105     }
4106     /* expected output */
4107     {
4108         out_data.resize(16 * 5);
4109         float *fp = reinterpret_cast<float *>(&out_data[0]);
4110         fp[0]     = 2.0f;
4111         fp[1]     = 0.0f;
4112         fp[2]     = 0.0f;
4113         fp[3]     = 0.0f;
4114         fp[4]     = 0.0f;
4115         fp[5]     = 3.0f;
4116         fp[6]     = 0.0f;
4117         fp[7]     = 0.0f;
4118         fp[8]     = 0.0f;
4119         fp[9]     = 0.0f;
4120         fp[10]    = 4.0f;
4121         fp[11]    = 0.0f;
4122         fp[12]    = 0.0f;
4123         fp[13]    = 0.0f;
4124         fp[14]    = 0.0f;
4125         fp[15]    = 5.0f;
4126 
4127         fp[16] = 0.0f;
4128         fp[17] = 1.0f;
4129         fp[18] = 4.0f;
4130         fp[19] = 0.0f;
4131     }
4132     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4 data0;" NL "  mat4 data1;" NL "} g_input;" NL
4133               "layout(std430, binding = 1) buffer Output {" NL "  mat4 data0;" NL "  vec4 data1;" NL "} g_output;" NL
4134               "uniform int g_index2 = 2;" NL "void main() {" NL
4135               "  g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
4136               "  g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
4137 }
4138 
4139 class BasicOperationsCase2VS : public BasicOperationsBaseVS
4140 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4141     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4142     {
4143         return GetInputOp2(in_data, out_data);
4144     }
4145 };
4146 
4147 class BasicOperationsCase2CS : public BasicOperationsBaseCS
4148 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4149     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
4150     {
4151         return GetInputOp2(in_data, out_data);
4152     }
4153 };
4154 
4155 //-----------------------------------------------------------------------------
4156 // 1.11.x BasicStdLayoutBase3
4157 //-----------------------------------------------------------------------------
4158 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
4159 {
4160     GLuint m_program;
4161     GLuint m_buffer[4];
4162     GLuint m_vertex_array;
4163 
4164     virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
4165 
Setup()4166     virtual long Setup()
4167     {
4168         m_program = 0;
4169         memset(m_buffer, 0, sizeof(m_buffer));
4170         m_vertex_array = 0;
4171         return NO_ERROR;
4172     }
4173 
Run()4174     virtual long Run()
4175     {
4176         if (!SupportedInVS(2))
4177             return NOT_SUPPORTED;
4178         std::vector<GLubyte> in_data[2];
4179         const char *glsl_vs = GetInput(in_data);
4180 
4181         m_program = CreateProgram(glsl_vs, "");
4182         glLinkProgram(m_program);
4183         if (!CheckProgram(m_program))
4184             return ERROR;
4185 
4186         glGenBuffers(4, m_buffer);
4187 
4188         // input buffers
4189         glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4190         glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4191 
4192         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4193         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4194 
4195         /* output buffer 0 */
4196         {
4197             std::vector<GLubyte> out_data(in_data[0].size());
4198             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4199             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4200         }
4201         /* output buffer 1 */
4202         {
4203             std::vector<GLubyte> out_data(in_data[1].size());
4204             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4205             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4206         }
4207 
4208         glGenVertexArrays(1, &m_vertex_array);
4209         glEnable(GL_RASTERIZER_DISCARD);
4210 
4211         glUseProgram(m_program);
4212         glBindVertexArray(m_vertex_array);
4213         glDrawArrays(GL_POINTS, 0, 1);
4214 
4215         bool status = true;
4216         for (int j = 0; j < 2; ++j)
4217         {
4218             std::vector<GLubyte> out_data(in_data[j].size());
4219             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4220             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4221             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
4222 
4223             for (size_t i = 0; i < in_data[j].size(); ++i)
4224             {
4225                 if (in_data[j][i] != out_data[i])
4226                 {
4227                     m_context.getTestContext().getLog()
4228                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4229                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4230                         << tcu::TestLog::EndMessage;
4231                     status = false;
4232                 }
4233             }
4234         }
4235         if (!status)
4236             return ERROR;
4237         return NO_ERROR;
4238     }
4239 
Cleanup()4240     virtual long Cleanup()
4241     {
4242         glDisable(GL_RASTERIZER_DISCARD);
4243         glUseProgram(0);
4244         glDeleteProgram(m_program);
4245         glDeleteBuffers(4, m_buffer);
4246         glDeleteVertexArrays(1, &m_vertex_array);
4247         return NO_ERROR;
4248     }
4249 };
4250 
4251 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4252 {
4253     GLuint m_program;
4254     GLuint m_buffer[4];
4255 
4256     virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
4257 
Setup()4258     virtual long Setup()
4259     {
4260         m_program = 0;
4261         memset(m_buffer, 0, sizeof(m_buffer));
4262         return NO_ERROR;
4263     }
4264 
Run()4265     virtual long Run()
4266     {
4267         std::vector<GLubyte> in_data[2];
4268 
4269         std::stringstream ss;
4270         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
4271         m_program = CreateProgramCS(ss.str());
4272         glLinkProgram(m_program);
4273         if (!CheckProgram(m_program))
4274             return ERROR;
4275 
4276         glGenBuffers(4, m_buffer);
4277 
4278         // input buffers
4279         glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4280         glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4281 
4282         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4283         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4284 
4285         /* output buffer 0 */
4286         {
4287             std::vector<GLubyte> out_data(in_data[0].size());
4288             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4289             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4290         }
4291         /* output buffer 1 */
4292         {
4293             std::vector<GLubyte> out_data(in_data[1].size());
4294             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4295             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4296         }
4297 
4298         glUseProgram(m_program);
4299         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4300         glDispatchCompute(1, 1, 1);
4301 
4302         bool status = true;
4303         for (int j = 0; j < 2; ++j)
4304         {
4305             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4306             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4307             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
4308                                                             GL_MAP_READ_BIT);
4309             if (!out_data)
4310                 return ERROR;
4311 
4312             for (size_t i = 0; i < in_data[j].size(); ++i)
4313             {
4314                 if (in_data[j][i] != out_data[i])
4315                 {
4316                     m_context.getTestContext().getLog()
4317                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4318                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4319                         << tcu::TestLog::EndMessage;
4320                     status = false;
4321                 }
4322             }
4323             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4324         }
4325         if (!status)
4326             return ERROR;
4327         return NO_ERROR;
4328     }
4329 
Cleanup()4330     virtual long Cleanup()
4331     {
4332         glUseProgram(0);
4333         glDeleteProgram(m_program);
4334         glDeleteBuffers(4, m_buffer);
4335         return NO_ERROR;
4336     }
4337 };
4338 //-----------------------------------------------------------------------------
4339 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4340 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4341 const char *GetInputUBO1(std::vector<GLubyte> in_data[2])
4342 {
4343     /* UBO */
4344     {
4345         in_data[0].resize(12 * 4);
4346         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4347         fp[0]     = 1.0f;
4348         fp[1]     = 0.0f;
4349         fp[2]     = 0.0f;
4350         fp[3]     = 0.0f;
4351         fp[4]     = 2.0f;
4352         fp[5]     = 0.0f;
4353         fp[6]     = 0.0f;
4354         fp[7]     = 0.0f;
4355         fp[8]     = 3.0f;
4356         fp[9]     = 0.0f;
4357         fp[10]    = 0.0f;
4358         fp[11]    = 0.0f;
4359     }
4360     /* SSBO */
4361     {
4362         in_data[1].resize(3 * 4);
4363         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4364         fp[0]     = 1.0f;
4365         fp[1]     = 2.0f;
4366         fp[2]     = 3.0f;
4367     }
4368     return NL
4369         "layout(std140, binding = 0) uniform InputUBO {" NL "  float data0;" NL "  float data1[2];" NL
4370         "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL "  float data0;" NL
4371         "  float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4372         "  float data0;" NL "  float data1[2];" NL "} g_output_ubo;" NL
4373         "layout(std430, binding = 2) buffer OutputSSBO {" NL "  float data0;" NL "  float data1[2];" NL
4374         "} g_output_ssbo;" NL "void main() {" NL "  g_output_ubo.data0 = g_input_ubo.data0;" NL
4375         "  for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4376         "  g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4377         "  for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4378         "}";
4379 }
4380 
4381 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4382 {
GetInput(std::vector<GLubyte> in_data[2])4383     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4384     {
4385         return GetInputUBO1(in_data);
4386     }
4387 };
4388 
4389 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4390 {
GetInput(std::vector<GLubyte> in_data[2])4391     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4392     {
4393         return GetInputUBO1(in_data);
4394     }
4395 };
4396 
4397 //-----------------------------------------------------------------------------
4398 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4399 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4400 const char *GetInputUBO2(std::vector<GLubyte> in_data[2])
4401 {
4402     /* UBO */
4403     {
4404         in_data[0].resize(280 * 4);
4405         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4406         int *ip   = reinterpret_cast<int *>(&in_data[0][0]);
4407         fp[0]     = 1.0f;
4408         fp[1]     = 2.0f;
4409         fp[2]     = 3.0f;
4410         fp[3]     = 4.0f;
4411         fp[4]     = 5.0f;
4412         fp[5]     = 6.0f;
4413         fp[6]     = 7.0f;
4414         fp[8]     = 9.0f;
4415         fp[12]    = 10.0f;
4416         fp[16]    = 11.0f;
4417         fp[20]    = 12.0f;
4418         fp[24]    = 13.0f;
4419 
4420         ip[28] = 14;
4421         for (int i = 0; i < 20; ++i)
4422         {
4423             fp[32 + i * 4] = static_cast<float>(15 + i);
4424         }
4425         ip[112] = 140;
4426         for (int i = 0; i < 20; ++i)
4427         {
4428             fp[116 + i * 4] = static_cast<float>(150 + i);
4429         }
4430         ip[196] = 1400;
4431         for (int i = 0; i < 20; ++i)
4432         {
4433             fp[200 + i * 4] = static_cast<float>(1500 + i);
4434         }
4435     }
4436     /* SSBO */
4437     {
4438         in_data[1].resize(76 * 4);
4439         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4440         int *ip   = reinterpret_cast<int *>(&in_data[1][0]);
4441         fp[0]     = 1.0f;
4442         fp[1]     = 2.0f;
4443         fp[2]     = 3.0f;
4444         fp[3]     = 4.0f;
4445         fp[4]     = 5.0f;
4446         fp[5]     = 6.0f;
4447         fp[6]     = 7.0f;
4448         fp[7]     = 8.0f;
4449         fp[8]     = 9.0f;
4450         fp[9]     = 10.0f;
4451         fp[10]    = 11.0f;
4452         fp[11]    = 12.0f;
4453         fp[12]    = 13.0f;
4454         ip[13]    = 14;
4455         fp[14]    = 15.0f;
4456         fp[15]    = 16.0f;
4457         fp[16]    = 17.0f;
4458         fp[17]    = 18.0f;
4459         fp[18]    = 19.0f;
4460         fp[19]    = 20.0f;
4461         fp[20]    = 21.0f;
4462         fp[21]    = 22.0f;
4463         fp[22]    = 23.0f;
4464         fp[23]    = 24.0f;
4465         fp[24]    = 25.0f;
4466         fp[25]    = 26.0f;
4467         fp[26]    = 27.0f;
4468         fp[27]    = 28.0f;
4469         fp[28]    = 29.0f;
4470         fp[29]    = 30.0f;
4471         fp[30]    = 31.0f;
4472         fp[31]    = 32.0f;
4473         fp[32]    = 33.0f;
4474         fp[33]    = 34.0f;
4475         ip[34]    = 35;
4476         fp[35]    = 36.0f;
4477         fp[36]    = 37.0f;
4478         fp[37]    = 38.0f;
4479         fp[38]    = 39.0f;
4480         fp[39]    = 40.0f;
4481         fp[40]    = 41.0f;
4482         fp[41]    = 42.0f;
4483         fp[42]    = 43.0f;
4484         fp[43]    = 44.0f;
4485         fp[44]    = 45.0f;
4486         fp[45]    = 46.0f;
4487         fp[46]    = 47.0f;
4488         fp[47]    = 48.0f;
4489         fp[48]    = 49.0f;
4490         fp[49]    = 50.0f;
4491         fp[50]    = 51.0f;
4492         fp[51]    = 52.0f;
4493         fp[52]    = 53.0f;
4494         fp[53]    = 54.0f;
4495         fp[54]    = 55.0f;
4496         ip[55]    = 56;
4497         fp[56]    = 57.0f;
4498         fp[57]    = 58.0f;
4499         fp[58]    = 59.0f;
4500         fp[59]    = 60.0f;
4501         fp[60]    = 61.0f;
4502         fp[61]    = 62.0f;
4503         fp[62]    = 63.0f;
4504         fp[63]    = 64.0f;
4505         fp[64]    = 65.0f;
4506         fp[65]    = 66.0f;
4507         fp[66]    = 67.0f;
4508         fp[67]    = 68.0f;
4509         fp[68]    = 69.0f;
4510         fp[69]    = 70.0f;
4511         fp[70]    = 71.0f;
4512         fp[71]    = 72.0f;
4513         fp[72]    = 73.0f;
4514         fp[73]    = 74.0f;
4515         fp[74]    = 75.0f;
4516         fp[75]    = 76.0f;
4517     }
4518     return NL
4519         "struct MM {" NL "  float mm_a[5];" NL "};" NL "struct TT {" NL "  int tt_a;" NL "  MM  tt_b[4];" NL "};" NL
4520         "layout(std140, binding = 0) uniform InputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4521         "  float d[4];" NL "  TT    e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4522         "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_input_ssbo;" NL
4523         "layout(std140, binding = 1) buffer OutputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4524         "  float d[4];" NL "  TT    e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4525         "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_output_ssbo;" NL
4526         "uniform int g_index1 = 1;" NL "void main() {" NL "  int index0 = 0;" NL NL
4527         "  g_output_ubo.a = g_input_ubo.a;" NL "  g_output_ubo.b = g_input_ubo.b;" NL
4528         "  g_output_ubo.c = g_input_ubo.c;" NL
4529         "  for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4530         "    for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4531         "    g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4532         "    for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4533         "      g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4534         "      g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4535         "      g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4536         "      g_output_ubo.e[j + 1 - g_index1].tt_b[i].mm_a[4 - g_index1] = g_input_ubo.e[j].tt_b[i].mm_a[2 + "
4537         "g_index1];" NL "      g_output_ubo.e[j].tt_b[i].mm_a[4] = g_input_ubo.e[j].tt_b[i - index0].mm_a[4];" NL
4538         "    }" NL "  }" NL NL "  g_output_ssbo.a = g_input_ssbo.a;" NL "  g_output_ssbo.b = g_input_ssbo.b;" NL
4539         "  g_output_ssbo.c = g_input_ssbo.c;" NL
4540         "  for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4541         "  for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4542         "    g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4543         "    for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4544         "      g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4545         "      g_output_ssbo.e[j].tt_b[i + index0].mm_a[1] = g_input_ssbo.e[j].tt_b[i].mm_a[g_index1];" NL
4546         "      g_output_ssbo.e[j].tt_b[i].mm_a[2] = g_input_ssbo.e[j].tt_b[i].mm_a[1 + g_index1];" NL
4547         "      g_output_ssbo.e[j - index0].tt_b[i].mm_a[g_index1 + 2] = g_input_ssbo.e[j].tt_b[i].mm_a[4 - "
4548         "g_index1];" NL "      g_output_ssbo.e[j].tt_b[i].mm_a[4] = g_input_ssbo.e[j].tt_b[i].mm_a[4];" NL "    }" NL
4549         "  }" NL "}";
4550 }
4551 
4552 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4553 {
GetInput(std::vector<GLubyte> in_data[2])4554     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4555     {
4556         return GetInputUBO2(in_data);
4557     }
4558 };
4559 
4560 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4561 {
GetInput(std::vector<GLubyte> in_data[2])4562     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4563     {
4564         return GetInputUBO2(in_data);
4565     }
4566 };
4567 
4568 //-----------------------------------------------------------------------------
4569 // 1.12.x BasicMatrixOperationsBase
4570 //-----------------------------------------------------------------------------
4571 
4572 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4573 {
4574     GLuint m_program;
4575     GLuint m_buffer[2];
4576     GLuint m_vertex_array;
4577 
4578     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4579 
Equal(float a,float b)4580     static bool Equal(float a, float b)
4581     {
4582         return fabsf(a - b) < 0.001f;
4583     }
4584 
Setup()4585     virtual long Setup()
4586     {
4587         m_program = 0;
4588         memset(m_buffer, 0, sizeof(m_buffer));
4589         m_vertex_array = 0;
4590         return NO_ERROR;
4591     }
4592 
Run()4593     virtual long Run()
4594     {
4595         if (!SupportedInVS(2))
4596             return NOT_SUPPORTED;
4597         std::vector<float> in;
4598         std::vector<float> expected;
4599         const char *glsl_vs = GetInput(in, expected);
4600 
4601         m_program = CreateProgram(glsl_vs, "");
4602         glLinkProgram(m_program);
4603         if (!CheckProgram(m_program))
4604             return ERROR;
4605 
4606         glGenBuffers(2, m_buffer);
4607 
4608         /* output buffer */
4609         {
4610             std::vector<float> zero(expected.size());
4611             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4612             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4613                          GL_STATIC_DRAW);
4614         }
4615         // input buffer
4616         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4617         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4618 
4619         glGenVertexArrays(1, &m_vertex_array);
4620         glEnable(GL_RASTERIZER_DISCARD);
4621 
4622         glUseProgram(m_program);
4623         glBindVertexArray(m_vertex_array);
4624         glDrawArrays(GL_POINTS, 0, 1);
4625 
4626         std::vector<float> out_data(expected.size());
4627         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4628         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4629         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)(out_data.size() * sizeof(float)), &out_data[0]);
4630 
4631         bool status = true;
4632         for (size_t i = 0; i < out_data.size(); ++i)
4633         {
4634             if (!Equal(expected[i], out_data[i]))
4635             {
4636                 m_context.getTestContext().getLog()
4637                     << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4638                     << " should be " << expected[i] << tcu::TestLog::EndMessage;
4639                 status = false;
4640             }
4641         }
4642         if (!status)
4643             return ERROR;
4644         return NO_ERROR;
4645     }
4646 
Cleanup()4647     virtual long Cleanup()
4648     {
4649         glDisable(GL_RASTERIZER_DISCARD);
4650         glUseProgram(0);
4651         glDeleteProgram(m_program);
4652         glDeleteBuffers(2, m_buffer);
4653         glDeleteVertexArrays(1, &m_vertex_array);
4654         return NO_ERROR;
4655     }
4656 };
4657 
4658 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4659 {
4660     GLuint m_program;
4661     GLuint m_buffer[2];
4662 
4663     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4664 
Equal(float a,float b)4665     static bool Equal(float a, float b)
4666     {
4667         return fabsf(a - b) < 0.001f;
4668     }
4669 
Setup()4670     virtual long Setup()
4671     {
4672         m_program = 0;
4673         memset(m_buffer, 0, sizeof(m_buffer));
4674         return NO_ERROR;
4675     }
4676 
Run()4677     virtual long Run()
4678     {
4679         std::vector<float> in;
4680         std::vector<float> expected;
4681         std::stringstream ss;
4682         ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4683         m_program = CreateProgramCS(ss.str());
4684         glLinkProgram(m_program);
4685         if (!CheckProgram(m_program))
4686             return ERROR;
4687 
4688         glGenBuffers(2, m_buffer);
4689 
4690         /* output buffer */
4691         {
4692             std::vector<float> zero(expected.size());
4693             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4694             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4695                          GL_STATIC_DRAW);
4696         }
4697         // input buffer
4698         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4699         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4700 
4701         glUseProgram(m_program);
4702         glDispatchCompute(1, 1, 1);
4703 
4704         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4705         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4706         float *out_data = (float *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4707                                                     (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4708         if (!out_data)
4709             return ERROR;
4710 
4711         bool status = true;
4712         for (size_t i = 0; i < expected.size(); ++i)
4713         {
4714             if (!Equal(expected[i], out_data[i]))
4715             {
4716                 m_context.getTestContext().getLog()
4717                     << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4718                     << " should be " << expected[i] << tcu::TestLog::EndMessage;
4719                 status = false;
4720             }
4721         }
4722         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4723         if (!status)
4724             return ERROR;
4725         return NO_ERROR;
4726     }
4727 
Cleanup()4728     virtual long Cleanup()
4729     {
4730         glUseProgram(0);
4731         glDeleteProgram(m_program);
4732         glDeleteBuffers(2, m_buffer);
4733         return NO_ERROR;
4734     }
4735 };
4736 //-----------------------------------------------------------------------------
4737 // 1.12.1 BasicMatrixOperationsCase1
4738 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4739 const char *GetInputM1(std::vector<float> &in, std::vector<float> &expected)
4740 {
4741     in.resize(8);
4742     in[0] = 1.0f;
4743     in[2] = 3.0f;
4744     in[1] = 2.0f;
4745     in[3] = 4.0f;
4746     in[4] = 1.0f;
4747     in[6] = 3.0f;
4748     in[5] = 2.0f;
4749     in[7] = 4.0f;
4750     expected.resize(4);
4751     expected[0] = 7.0f;
4752     expected[2] = 15.0f;
4753     expected[1] = 10.0f;
4754     expected[3] = 22.0f;
4755 
4756     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat2 m0;" NL "  mat2 m1;" NL "} g_input;" NL
4757               "layout(std430, binding = 1) buffer Output {" NL "  mat2 m;" NL "} g_output;" NL
4758               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4759 }
4760 
4761 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4762 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4763     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4764     {
4765         return GetInputM1(in, expected);
4766     }
4767 };
4768 
4769 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4770 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4771     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4772     {
4773         return GetInputM1(in, expected);
4774     }
4775 };
4776 
4777 //-----------------------------------------------------------------------------
4778 // 1.12.2 BasicMatrixOperationsCase2
4779 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4780 const char *GetInputM2(std::vector<float> &in, std::vector<float> &expected)
4781 {
4782     in.resize(16);
4783     expected.resize(4);
4784     // mat3x2
4785     in[0] = 1.0f;
4786     in[2] = 3.0f;
4787     in[4] = 5.0f;
4788     in[1] = 2.0f;
4789     in[3] = 4.0f;
4790     in[5] = 6.0f;
4791     // mat2x3
4792     in[8]  = 1.0f;
4793     in[12] = 4.0f;
4794     in[9]  = 2.0f;
4795     in[13] = 5.0f;
4796     in[10] = 3.0f;
4797     in[14] = 6.0f;
4798     // mat2
4799     expected[0] = 22.0f;
4800     expected[2] = 49.0f;
4801     expected[1] = 28.0f;
4802     expected[3] = 64.0f;
4803 
4804     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4805               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4806               "  layout(column_major) mat2 m;" NL "} g_output;" NL
4807               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4808 }
4809 
4810 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4811 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4812     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4813     {
4814         return GetInputM2(in, expected);
4815     }
4816 };
4817 
4818 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4819 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4820     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4821     {
4822         return GetInputM2(in, expected);
4823     }
4824 };
4825 
4826 //-----------------------------------------------------------------------------
4827 // 1.12.3 BasicMatrixOperationsCase3
4828 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4829 const char *GetInputM3(std::vector<float> &in, std::vector<float> &expected)
4830 {
4831     in.resize(16);
4832     expected.resize(4);
4833     // row major mat3x2
4834     in[0] = 1.0f;
4835     in[1] = 3.0f;
4836     in[2] = 5.0f;
4837     in[4] = 2.0f;
4838     in[5] = 4.0f;
4839     in[6] = 6.0f;
4840     // row major mat2x3
4841     in[8]  = 1.0f;
4842     in[9]  = 4.0f;
4843     in[10] = 2.0f;
4844     in[11] = 5.0f;
4845     in[12] = 3.0f;
4846     in[13] = 6.0f;
4847     // row major mat2
4848     expected[0] = 22.0f;
4849     expected[1] = 49.0f;
4850     expected[2] = 28.0f;
4851     expected[3] = 64.0f;
4852 
4853     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4854               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4855               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4856 }
4857 
4858 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4859 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4860     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4861     {
4862         return GetInputM3(in, expected);
4863     }
4864 };
4865 
4866 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4867 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4868     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4869     {
4870         return GetInputM3(in, expected);
4871     }
4872 };
4873 
4874 //-----------------------------------------------------------------------------
4875 // 1.12.4 BasicMatrixOperationsCase4
4876 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4877 const char *GetInputM4(std::vector<float> &in, std::vector<float> &expected)
4878 {
4879     in.resize(16);
4880     expected.resize(4);
4881     // column major mat3x2
4882     in[0] = 1.0f;
4883     in[2] = 3.0f;
4884     in[4] = 5.0f;
4885     in[1] = 2.0f;
4886     in[3] = 4.0f;
4887     in[5] = 6.0f;
4888     // row major mat2x3
4889     in[8]  = 1.0f;
4890     in[9]  = 4.0f;
4891     in[10] = 2.0f;
4892     in[11] = 5.0f;
4893     in[12] = 3.0f;
4894     in[13] = 6.0f;
4895     // column major mat2
4896     expected[0] = 13.0f;
4897     expected[1] = 16.0f;
4898     expected[2] = 37.0f;
4899     expected[3] = 46.0f;
4900 
4901     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4902               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4903               "  layout(column_major) mat2 m;" NL "} g_output;" NL
4904               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4905 }
4906 
4907 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4908 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4909     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4910     {
4911         return GetInputM4(in, expected);
4912     }
4913 };
4914 
4915 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4916 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4917     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4918     {
4919         return GetInputM4(in, expected);
4920     }
4921 };
4922 
4923 //-----------------------------------------------------------------------------
4924 // 1.12.5 BasicMatrixOperationsCase5
4925 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4926 const char *GetInputM5(std::vector<float> &in, std::vector<float> &expected)
4927 {
4928     in.resize(16);
4929     expected.resize(4);
4930     // column major mat3x2
4931     in[0] = 1.0f;
4932     in[2] = 3.0f;
4933     in[4] = 5.0f;
4934     in[1] = 2.0f;
4935     in[3] = 4.0f;
4936     in[5] = 6.0f;
4937     // row major mat2x3
4938     in[8]  = 1.0f;
4939     in[9]  = 4.0f;
4940     in[10] = 2.0f;
4941     in[11] = 5.0f;
4942     in[12] = 3.0f;
4943     in[13] = 6.0f;
4944     // row major mat2
4945     expected[0] = 13.0f;
4946     expected[1] = 37.0f;
4947     expected[2] = 16.0f;
4948     expected[3] = 46.0f;
4949 
4950     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4951               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4952               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4953 }
4954 
4955 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4956 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4957     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4958     {
4959         return GetInputM5(in, expected);
4960     }
4961 };
4962 
4963 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4964 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4965     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4966     {
4967         return GetInputM5(in, expected);
4968     }
4969 };
4970 
4971 //-----------------------------------------------------------------------------
4972 // 1.12.6 BasicMatrixOperationsCase6
4973 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4974 const char *GetInputM6(std::vector<float> &in, std::vector<float> &expected)
4975 {
4976     in.resize(20);
4977     expected.resize(4);
4978     // row major mat3x2
4979     in[0] = 1.0f;
4980     in[1] = 3.0f;
4981     in[2] = 5.0f;
4982     in[4] = 2.0f;
4983     in[5] = 4.0f;
4984     in[6] = 6.0f;
4985     // column major mat2x3
4986     in[8]  = 1.0f;
4987     in[12] = 4.0f;
4988     in[9]  = 2.0f;
4989     in[13] = 5.0f;
4990     in[10] = 3.0f;
4991     in[14] = 6.0f;
4992     // column major mat2
4993     expected[0] = 22.0f;
4994     expected[1] = 28.0f;
4995     expected[2] = 49.0f;
4996     expected[3] = 64.0f;
4997 
4998     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4999               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5000               "  layout(column_major) mat2 m;" NL "} g_output;" NL
5001               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5002 }
5003 
5004 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
5005 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5006     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5007     {
5008         return GetInputM6(in, expected);
5009     }
5010 };
5011 
5012 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
5013 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5014     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5015     {
5016         return GetInputM6(in, expected);
5017     }
5018 };
5019 //-----------------------------------------------------------------------------
5020 // 1.12.7 BasicMatrixOperationsCase7
5021 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)5022 const char *GetInputM7(std::vector<float> &in, std::vector<float> &expected)
5023 {
5024     in.resize(20);
5025     expected.resize(4);
5026     // row major mat3x2
5027     in[0] = 1.0f;
5028     in[1] = 3.0f;
5029     in[2] = 5.0f;
5030     in[4] = 2.0f;
5031     in[5] = 4.0f;
5032     in[6] = 6.0f;
5033     // column major mat2x3
5034     in[8]  = 1.0f;
5035     in[12] = 4.0f;
5036     in[9]  = 2.0f;
5037     in[13] = 5.0f;
5038     in[10] = 3.0f;
5039     in[14] = 6.0f;
5040     // row major mat2
5041     expected[0] = 22.0f;
5042     expected[1] = 49.0f;
5043     expected[2] = 28.0f;
5044     expected[3] = 64.0f;
5045 
5046     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
5047               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5048               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5049 }
5050 
5051 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
5052 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5053     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5054     {
5055         return GetInputM7(in, expected);
5056     }
5057 };
5058 
5059 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
5060 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5061     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
5062     {
5063         return GetInputM7(in, expected);
5064     }
5065 };
5066 
5067 //-----------------------------------------------------------------------------
5068 // 1.13 BasicNoBindingLayout
5069 //-----------------------------------------------------------------------------
5070 class BasicNoBindingLayout : public ShaderStorageBufferObjectBase
5071 {
5072     GLuint m_vsp, m_ppo, m_ssbo, m_vao;
5073 
Setup()5074     virtual long Setup()
5075     {
5076         m_vsp = 0;
5077         glGenProgramPipelines(1, &m_ppo);
5078         glGenBuffers(1, &m_ssbo);
5079         glGenVertexArrays(1, &m_vao);
5080         return NO_ERROR;
5081     }
5082 
Cleanup()5083     virtual long Cleanup()
5084     {
5085         glDisable(GL_RASTERIZER_DISCARD);
5086         glDeleteProgram(m_vsp);
5087         glDeleteProgramPipelines(1, &m_ppo);
5088         glDeleteBuffers(1, &m_ssbo);
5089         glDeleteVertexArrays(1, &m_vao);
5090         return NO_ERROR;
5091     }
5092 
Run()5093     virtual long Run()
5094     {
5095         if (!SupportedInVS(3))
5096             return NOT_SUPPORTED;
5097 
5098         const char *const glsl_vs = "#version 430 core" NL "layout(std430) buffer Output0 { int data; } g_output0;" NL
5099                                     "layout(std430) buffer Output1 { int g_output1; };" NL
5100                                     "layout(std430) buffer Output2 { int data; } g_output2;" NL "void main() {" NL
5101                                     "  g_output0.data = 1;" NL "  g_output1 = 2;" NL "  g_output2.data = 3;" NL "}";
5102         m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
5103         if (!CheckProgram(m_vsp))
5104             return ERROR;
5105         glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
5106 
5107         glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output0"), 1);
5108         glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output1"), 5);
5109         glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output2"), 7);
5110 
5111         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5112         glBufferData(GL_SHADER_STORAGE_BUFFER, 1024, NULL, GL_DYNAMIC_DRAW);
5113         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, m_ssbo, 0, 4);
5114         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 5, m_ssbo, 256, 4);
5115         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_ssbo, 512, 4);
5116 
5117         glEnable(GL_RASTERIZER_DISCARD);
5118         glBindProgramPipeline(m_ppo);
5119         glBindVertexArray(m_vao);
5120         glDrawArrays(GL_POINTS, 0, 1);
5121 
5122         int data;
5123         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5124         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5125         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &data);
5126         if (data != 1)
5127             return ERROR;
5128         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 256, 4, &data);
5129         if (data != 2)
5130             return ERROR;
5131         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 512, 4, &data);
5132         if (data != 3)
5133             return ERROR;
5134 
5135         return NO_ERROR;
5136     }
5137 };
5138 
5139 //----------------------------------------------------------------------------
5140 // 1.14 BasicReadonlyWriteonly
5141 //-----------------------------------------------------------------------------
5142 class BasicReadonlyWriteonly : public ShaderStorageBufferObjectBase
5143 {
5144     GLuint m_program;
5145     GLuint m_storage_buffer[2];
5146 
Setup()5147     virtual long Setup()
5148     {
5149         m_program = 0;
5150         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5151         return NO_ERROR;
5152     }
5153 
Run()5154     virtual long Run()
5155     {
5156         const char *const glsl_cs =
5157             NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Input {" NL
5158                "  readonly writeonly int g_in[];" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL
5159                "  int count;" NL "} g_output;" NL "void main() {" NL "  g_output.count = g_in.length();" NL "}";
5160 
5161         m_program = CreateProgramCS(glsl_cs);
5162         glLinkProgram(m_program);
5163         if (!CheckProgram(m_program))
5164             return ERROR;
5165 
5166         glGenBuffers(2, m_storage_buffer);
5167 
5168         /* Input */
5169         int input_data[] = {1, 2, 3};
5170         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5171         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(input_data), input_data, GL_STATIC_DRAW);
5172 
5173         /* Output */
5174         int output_data[] = {0};
5175         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5176         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(output_data), output_data, GL_DYNAMIC_COPY);
5177 
5178         glUseProgram(m_program);
5179         glDispatchCompute(1, 1, 1);
5180         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5181 
5182         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5183         int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
5184         if (!data)
5185             return ERROR;
5186         if (*data != DE_LENGTH_OF_ARRAY(input_data))
5187         {
5188             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer data is " << *data << " should be "
5189                                                 << sizeof(input_data) << tcu::TestLog::EndMessage;
5190             return ERROR;
5191         }
5192         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5193         return NO_ERROR;
5194     }
5195 
Cleanup()5196     virtual long Cleanup()
5197     {
5198         glUseProgram(0);
5199         glDeleteProgram(m_program);
5200         glDeleteBuffers(2, m_storage_buffer);
5201         return NO_ERROR;
5202     }
5203 };
5204 
5205 //----------------------------------------------------------------------------
5206 // 1.15 BasicNameMatch
5207 //-----------------------------------------------------------------------------
5208 class BasicNameMatch : public ShaderStorageBufferObjectBase
5209 {
Run()5210     virtual long Run()
5211     {
5212         GLint blocksVS, blocksFS;
5213         glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
5214         glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
5215         if ((blocksVS == 0) || (blocksFS == 0))
5216             return NOT_SUPPORTED;
5217 
5218         // check if link error is generated when one of matched blocks has instance name and other doesn't
5219         std::string vs1("buffer Buf { float x; };\n"
5220                         "void main() {\n"
5221                         "  gl_Position = vec4(x);\n"
5222                         "}");
5223         std::string fs1("buffer Buf { float x; } b;\n"
5224                         "out vec4 color;\n"
5225                         "void main() {\n"
5226                         "  color = vec4(b.x);\n"
5227                         "}");
5228         if (Link(vs1, fs1))
5229         {
5230             m_context.getTestContext().getLog()
5231                 << tcu::TestLog::Message << "Linking should fail." << tcu::TestLog::EndMessage;
5232             return ERROR;
5233         }
5234 
5235         // check if linking succeeds when both matched blocks are lacking an instance name
5236         std::string vs2("buffer Buf { float x; };\n"
5237                         "void main() {\n"
5238                         "  gl_Position = vec4(x);\n"
5239                         "}");
5240         std::string fs2("buffer Buf { float x; };\n"
5241                         "out vec4 color;\n"
5242                         "void main() {\n"
5243                         "  color = vec4(x);\n"
5244                         "}");
5245         if (!Link(vs2, fs2))
5246         {
5247             m_context.getTestContext().getLog()
5248                 << tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5249             return ERROR;
5250         }
5251 
5252         // check if linking succeeds when both matched blocks have different instance names
5253         std::string vs3("buffer Buf { float x; } a;\n"
5254                         "void main() {\n"
5255                         "  gl_Position = vec4(a.x);\n"
5256                         "}");
5257         std::string fs3("buffer Buf { float x; } b;\n"
5258                         "out vec4 color;\n"
5259                         "void main() {\n"
5260                         "  color = vec4(b.x);\n"
5261                         "}");
5262         if (!Link(vs3, fs3))
5263         {
5264             m_context.getTestContext().getLog()
5265                 << tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5266             return ERROR;
5267         }
5268 
5269         return NO_ERROR;
5270     }
5271 
Link(const std::string & vs,const std::string & fs)5272     bool Link(const std::string &vs, const std::string &fs)
5273     {
5274         GLuint program = CreateProgram(vs, fs);
5275         glLinkProgram(program);
5276         GLint status;
5277         glGetProgramiv(program, GL_LINK_STATUS, &status);
5278         glDeleteProgram(program);
5279         return (status == GL_TRUE);
5280     }
5281 };
5282 
5283 //-----------------------------------------------------------------------------
5284 // 2.1 AdvancedSwitchBuffers
5285 //-----------------------------------------------------------------------------
5286 class AdvancedSwitchBuffers : public ShaderStorageBufferObjectBase
5287 {
5288     GLuint m_program;
5289     GLuint m_storage_buffer[5];
5290     GLuint m_vertex_array;
5291     GLuint m_fbo, m_rt;
5292 
Setup()5293     virtual long Setup()
5294     {
5295         m_program = 0;
5296         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5297         m_vertex_array = 0;
5298         glGenFramebuffers(1, &m_fbo);
5299         glGenTextures(1, &m_rt);
5300         return NO_ERROR;
5301     }
5302 
Run()5303     virtual long Run()
5304     {
5305         if (!SupportedInVS(1))
5306             return NOT_SUPPORTED;
5307 
5308         const char *const glsl_vs =
5309             NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5310                "layout(binding = 0, std430) buffer Input {" NL "  VertexData vertex[];" NL "} g_vs_in;" NL
5311                "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5312                "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5313                "  g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5314 
5315         const char *const glsl_fs =
5316             NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5317                "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5318         m_program = CreateProgram(glsl_vs, glsl_fs);
5319         glLinkProgram(m_program);
5320         if (!CheckProgram(m_program))
5321             return ERROR;
5322 
5323         glGenBuffers(5, m_storage_buffer);
5324 
5325         /* left, bottom, red quad */
5326         {
5327             const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5328                                   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5329                                   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5330                                   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
5331             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5332             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5333         }
5334         /* right, bottom, green quad */
5335         {
5336             const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5337                                   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5338                                   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5339                                   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
5340             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5341             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5342         }
5343         /* left, top, blue quad */
5344         {
5345             const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5346                                   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5347                                   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5348                                   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
5349             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5350             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5351         }
5352         /* right, top, yellow quad */
5353         {
5354             const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5355                                   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5356                                   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5357                                   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
5358             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5359             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5360         }
5361 
5362         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5363         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
5364 
5365         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5366         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
5367         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5368         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
5369         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5370         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
5371                             sizeof(float) * 32);
5372         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5373         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
5374                             sizeof(float) * 32);
5375 
5376         glBindTexture(GL_TEXTURE_2D, m_rt);
5377         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5378         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5379         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5380         glBindTexture(GL_TEXTURE_2D, 0);
5381         glViewport(0, 0, 100, 100);
5382         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5383         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5384 
5385         glGenVertexArrays(1, &m_vertex_array);
5386 
5387         glUseProgram(m_program);
5388         glBindVertexArray(m_vertex_array);
5389 
5390         glClear(GL_COLOR_BUFFER_BIT);
5391         for (int i = 0; i < 4; ++i)
5392         {
5393             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5394             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5395         }
5396         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5397         {
5398             return ERROR;
5399         }
5400 
5401         glClear(GL_COLOR_BUFFER_BIT);
5402         for (int i = 0; i < 4; ++i)
5403         {
5404             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5405                               sizeof(float) * 32);
5406             glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5407         }
5408         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5409         {
5410             return ERROR;
5411         }
5412 
5413         return NO_ERROR;
5414     }
5415 
Cleanup()5416     virtual long Cleanup()
5417     {
5418         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5419         glUseProgram(0);
5420         glDeleteProgram(m_program);
5421         glDeleteBuffers(5, m_storage_buffer);
5422         glDeleteVertexArrays(1, &m_vertex_array);
5423         glDeleteFramebuffers(1, &m_fbo);
5424         glDeleteTextures(1, &m_rt);
5425         return NO_ERROR;
5426     }
5427 };
5428 
5429 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5430 {
5431     GLuint m_program;
5432     GLuint m_storage_buffer[6];
5433 
Setup()5434     virtual long Setup()
5435     {
5436         m_program = 0;
5437         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5438         return NO_ERROR;
5439     }
5440 
Run()5441     virtual long Run()
5442     {
5443         const char *const glsl_cs =
5444             NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL "  uint cookie[4];" NL
5445                "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL
5446                "void main() {" NL "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5447                "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5448                "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5449                "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5450                "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5451         m_program = CreateProgramCS(glsl_cs);
5452         glLinkProgram(m_program);
5453         if (!CheckProgram(m_program))
5454             return ERROR;
5455 
5456         glGenBuffers(6, m_storage_buffer);
5457 
5458         const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5459         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5460         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5461         const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5462         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5463         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5464         const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5465         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5466         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5467         const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5468         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5469         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5470 
5471         GLint alignment;
5472         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5473         GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5474         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5475         glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5476 
5477         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5478         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5479         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5480         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5481         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5482         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5483         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5484         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5485 
5486         const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5487         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5488         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5489 
5490         glUseProgram(m_program);
5491         for (int i = 0; i < 4; ++i)
5492         {
5493             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5494             glDispatchCompute(1, 1, 1);
5495         }
5496         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5497         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5498         GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5499         if (!out_data)
5500             return ERROR;
5501         GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5502         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5503             out_data[3] != expected[3])
5504         {
5505             m_context.getTestContext().getLog()
5506                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5507                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5508                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5509                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5510             return ERROR;
5511         }
5512         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5513         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5514 
5515         for (int i = 0; i < 4; ++i)
5516         {
5517             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5518             glDispatchCompute(1, 1, 1);
5519         }
5520         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5521         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5522         out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5523         if (!out_data)
5524             return ERROR;
5525         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5526             out_data[3] != expected[3])
5527         {
5528             m_context.getTestContext().getLog()
5529                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5530                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5531                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5532                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5533             return ERROR;
5534         }
5535 
5536         return NO_ERROR;
5537     }
5538 
Cleanup()5539     virtual long Cleanup()
5540     {
5541         glUseProgram(0);
5542         glDeleteProgram(m_program);
5543         glDeleteBuffers(6, m_storage_buffer);
5544         return NO_ERROR;
5545     }
5546 };
5547 //-----------------------------------------------------------------------------
5548 // 2.2 AdvancedSwitchPrograms
5549 //-----------------------------------------------------------------------------
5550 
5551 class AdvancedSwitchPrograms : public ShaderStorageBufferObjectBase
5552 {
5553     GLuint m_program[4];
5554     GLuint m_storage_buffer[4];
5555     GLuint m_vertex_array;
5556     GLuint m_fbo, m_rt;
5557 
GenSource(int binding)5558     std::string GenSource(int binding)
5559     {
5560         std::stringstream ss;
5561         ss << NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL "layout(binding = "
5562            << binding
5563            << ", std430) buffer Input {" NL "  VertexData vertex[];" NL "} g_vs_in;" NL "out StageData {" NL
5564               "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5565               "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5566               "  g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5567         return ss.str();
5568     }
5569 
Setup()5570     virtual long Setup()
5571     {
5572         memset(m_program, 0, sizeof(m_program));
5573         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5574         m_vertex_array = 0;
5575         glGenFramebuffers(1, &m_fbo);
5576         glGenTextures(1, &m_rt);
5577         return NO_ERROR;
5578     }
5579 
Run()5580     virtual long Run()
5581     {
5582         if (!SupportedInVS(1))
5583             return NOT_SUPPORTED;
5584 
5585         const char *const glsl_fs =
5586             NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5587                "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5588         for (int i = 0; i < 4; ++i)
5589         {
5590             m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5591             glLinkProgram(m_program[i]);
5592             if (!CheckProgram(m_program[i]))
5593                 return ERROR;
5594         }
5595 
5596         glGenBuffers(4, m_storage_buffer);
5597 
5598         /* left, bottom, red quad */
5599         {
5600             const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5601                                   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5602                                   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5603                                   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
5604             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5605             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5606         }
5607         /* right, bottom, green quad */
5608         {
5609             const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5610                                   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5611                                   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5612                                   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
5613             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5614             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5615         }
5616         /* left, top, blue quad */
5617         {
5618             const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5619                                   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5620                                   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5621                                   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
5622             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5623             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5624         }
5625         /* right, top, yellow quad */
5626         {
5627             const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5628                                   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5629                                   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5630                                   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
5631             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5632             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5633         }
5634 
5635         glBindTexture(GL_TEXTURE_2D, m_rt);
5636         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5637         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5638         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5639         glBindTexture(GL_TEXTURE_2D, 0);
5640         glViewport(0, 0, 100, 100);
5641         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5642         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5643 
5644         glGenVertexArrays(1, &m_vertex_array);
5645         glBindVertexArray(m_vertex_array);
5646 
5647         glClear(GL_COLOR_BUFFER_BIT);
5648         for (int i = 0; i < 4; ++i)
5649         {
5650             glUseProgram(m_program[i]);
5651             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5652         }
5653         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5654         {
5655             return ERROR;
5656         }
5657 
5658         glClear(GL_COLOR_BUFFER_BIT);
5659         glShaderStorageBlockBinding(m_program[0], 0, 3);
5660         glUseProgram(m_program[0]);
5661         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5662         if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(1, 1, 0), vec3(0)))
5663         {
5664             return ERROR;
5665         }
5666 
5667         glClear(GL_COLOR_BUFFER_BIT);
5668         glShaderStorageBlockBinding(m_program[3], 0, 0);
5669         glUseProgram(m_program[3]);
5670         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5671         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0), vec3(0), vec3(0)))
5672         {
5673             return ERROR;
5674         }
5675 
5676         return NO_ERROR;
5677     }
5678 
Cleanup()5679     virtual long Cleanup()
5680     {
5681         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5682         glUseProgram(0);
5683         for (int i = 0; i < 4; ++i)
5684             glDeleteProgram(m_program[i]);
5685         glDeleteBuffers(4, m_storage_buffer);
5686         glDeleteVertexArrays(1, &m_vertex_array);
5687         glDeleteFramebuffers(1, &m_fbo);
5688         glDeleteTextures(1, &m_rt);
5689         return NO_ERROR;
5690     }
5691 };
5692 
5693 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5694 {
5695     GLuint m_program[4];
5696     GLuint m_storage_buffer[5];
5697 
Setup()5698     virtual long Setup()
5699     {
5700         memset(m_program, 0, sizeof(m_program));
5701         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5702         return NO_ERROR;
5703     }
5704 
GenSource(int binding)5705     std::string GenSource(int binding)
5706     {
5707         std::stringstream ss;
5708         ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5709            << ", std430) buffer Input {" NL "  uint cookie[4];" NL "} g_in;" NL
5710               "layout(binding = 0, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL "void main() {" NL
5711               "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5712               "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5713               "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5714               "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5715               "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5716         return ss.str();
5717     }
5718 
Run()5719     virtual long Run()
5720     {
5721         for (int i = 0; i < 4; ++i)
5722         {
5723             m_program[i] = CreateProgramCS(GenSource(i + 1));
5724             glLinkProgram(m_program[i]);
5725             if (!CheckProgram(m_program[i]))
5726                 return ERROR;
5727         }
5728 
5729         glGenBuffers(5, m_storage_buffer);
5730 
5731         const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5732         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5733         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5734         const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5735         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5736         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5737         const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5738         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5739         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5740         const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5741         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5742         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5743 
5744         const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5745         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5746         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5747 
5748         for (int i = 0; i < 4; ++i)
5749         {
5750             glUseProgram(m_program[i]);
5751             glDispatchCompute(1, 1, 1);
5752         }
5753         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5754         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5755         GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5756         if (!out_data)
5757             return ERROR;
5758         GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5759         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5760             out_data[3] != expected[3])
5761         {
5762             m_context.getTestContext().getLog()
5763                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5764                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5765                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5766                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5767             return ERROR;
5768         }
5769         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5770 
5771         return NO_ERROR;
5772     }
5773 
Cleanup()5774     virtual long Cleanup()
5775     {
5776         glUseProgram(0);
5777         for (int i = 0; i < 4; ++i)
5778             glDeleteProgram(m_program[i]);
5779         glDeleteBuffers(5, m_storage_buffer);
5780         return NO_ERROR;
5781     }
5782 };
5783 //-----------------------------------------------------------------------------
5784 // 2.3.1 AdvancedWriteFragment
5785 //-----------------------------------------------------------------------------
5786 
5787 class AdvancedWriteFragment : public ShaderStorageBufferObjectBase
5788 {
5789     GLuint m_program[2];
5790     GLuint m_storage_buffer;
5791     GLuint m_counter_buffer;
5792     GLuint m_attribless_vertex_array;
5793     GLuint m_draw_vertex_array;
5794     GLuint m_fbo, m_rt;
5795 
Setup()5796     virtual long Setup()
5797     {
5798         memset(m_program, 0, sizeof(m_program));
5799         m_storage_buffer          = 0;
5800         m_counter_buffer          = 0;
5801         m_attribless_vertex_array = 0;
5802         m_draw_vertex_array       = 0;
5803         glGenFramebuffers(1, &m_fbo);
5804         glGenTextures(1, &m_rt);
5805         return NO_ERROR;
5806     }
5807 
Run()5808     virtual long Run()
5809     {
5810         const char *const glsl_vs0 = NL
5811             "out StageData {" NL "  vec2 position;" NL "  vec3 color;" NL "} g_vs_out;" NL
5812             "const vec2 g_quad[4] = vec2[4](vec2(-0.4, -0.4), vec2(0.4, -0.4), vec2(-0.4, 0.4), vec2(0.4, 0.4));" NL
5813             "const vec2 g_offset[4] = vec2[4](vec2(-0.5, -0.5), vec2(0.5, -0.5), vec2(-0.5, 0.5), vec2(0.5, 0.5));" NL
5814             "const vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5815             "void main() {" NL "  vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5816             "  gl_Position = vec4(pos, 0, 1);" NL "  g_vs_out.position = pos;" NL
5817             "  g_vs_out.color = g_color[gl_InstanceID];" NL "}";
5818 
5819         const char *const glsl_fs0 =
5820             NL "in StageData {" NL "  vec2 position;" NL "  vec3 color;" NL "} g_fs_in;" NL
5821                "layout(location = 0) out vec4 g_fs_out;" NL "struct FragmentData {" NL "  vec2 position;" NL
5822                "  vec3 color;" NL "};" NL "layout(std430, binding = 3) buffer Output {" NL
5823                "  FragmentData g_fragment[];" NL "};" NL "uniform uint g_max_fragment_count = 100 * 100;" NL
5824                "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5825                "  uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5826                "  if (fragment_number < g_max_fragment_count) {" NL
5827                "    g_fragment[fragment_number].position = g_fs_in.position;" NL
5828                "    g_fragment[fragment_number].color = g_fs_in.color;" NL "  }" NL
5829                "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5830 
5831         m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5832         glLinkProgram(m_program[0]);
5833         if (!CheckProgram(m_program[0]))
5834             return ERROR;
5835 
5836         const char *const glsl_vs1 =
5837             NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5838                "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5839                "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL "  g_vs_out.color = g_in_color.rgb;" NL "}";
5840 
5841         const char *const glsl_fs1 =
5842             NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5843                "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5844 
5845         m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5846         glLinkProgram(m_program[1]);
5847         if (!CheckProgram(m_program[1]))
5848             return ERROR;
5849 
5850         // The first pass renders four squares on-screen, and writes a
5851         // record to the SSBO for each fragment processed.  The rectangles
5852         // will be 40x40 when using a 100x100 viewport, so we expect 1600
5853         // pixels per rectangle or 6400 pixels total.  Size the SSBO
5854         // accordingly, and render the second pass (sourcing the SSBO as a
5855         // vertex buffer) with an identical number of points.  If we have
5856         // a larger buffer and draw more points on the second pass, those
5857         // may overwrite "real" points using garbage position/color.
5858         int expectedPixels = 6400;
5859 
5860         glGenBuffers(1, &m_storage_buffer);
5861         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5862         glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5863 
5864         glGenBuffers(1, &m_counter_buffer);
5865         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5866         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5867         uvec4 zero(0);
5868         glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5869 
5870         glBindTexture(GL_TEXTURE_2D, m_rt);
5871         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5872         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5873         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5874         glBindTexture(GL_TEXTURE_2D, 0);
5875         glViewport(0, 0, 100, 100);
5876         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5877         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5878 
5879         glGenVertexArrays(1, &m_attribless_vertex_array);
5880 
5881         glGenVertexArrays(1, &m_draw_vertex_array);
5882         glBindVertexArray(m_draw_vertex_array);
5883         glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5884         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5885         glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
5886         glBindBuffer(GL_ARRAY_BUFFER, 0);
5887         glEnableVertexAttribArray(0);
5888         glEnableVertexAttribArray(1);
5889         glBindVertexArray(0);
5890 
5891         glClear(GL_COLOR_BUFFER_BIT);
5892         glUseProgram(m_program[0]);
5893         glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5894         glBindVertexArray(m_attribless_vertex_array);
5895         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5896 
5897         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5898         {
5899             return ERROR;
5900         }
5901 
5902         glClear(GL_COLOR_BUFFER_BIT);
5903         glUseProgram(m_program[1]);
5904         glBindVertexArray(m_draw_vertex_array);
5905         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5906         glDrawArrays(GL_POINTS, 0, expectedPixels);
5907         int bad_pixels;
5908 
5909         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5910             bad_pixels > 2)
5911         {
5912             return ERROR;
5913         }
5914 
5915         return NO_ERROR;
5916     }
5917 
Cleanup()5918     virtual long Cleanup()
5919     {
5920         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5921         glUseProgram(0);
5922         for (int i = 0; i < 2; ++i)
5923             glDeleteProgram(m_program[i]);
5924         glDeleteBuffers(1, &m_storage_buffer);
5925         glDeleteBuffers(1, &m_counter_buffer);
5926         glDeleteVertexArrays(1, &m_attribless_vertex_array);
5927         glDeleteVertexArrays(1, &m_draw_vertex_array);
5928         glDeleteFramebuffers(1, &m_fbo);
5929         glDeleteTextures(1, &m_rt);
5930         return NO_ERROR;
5931     }
5932 };
5933 
5934 //-----------------------------------------------------------------------------
5935 // 2.3.2 AdvancedWriteGeometry
5936 //-----------------------------------------------------------------------------
5937 class AdvancedWriteGeometry : public ShaderStorageBufferObjectBase
5938 {
5939     GLuint m_program[2];
5940     GLuint m_storage_buffer;
5941     GLuint m_vertex_array[2];
5942     GLuint m_vertex_buffer;
5943 
Setup()5944     virtual long Setup()
5945     {
5946         memset(m_program, 0, sizeof(m_program));
5947         m_storage_buffer = 0;
5948         memset(m_vertex_array, 0, sizeof(m_vertex_array));
5949         m_vertex_buffer = 0;
5950         return NO_ERROR;
5951     }
5952 
Run()5953     virtual long Run()
5954     {
5955         if (!SupportedInGS(1))
5956             return NOT_SUPPORTED;
5957 
5958         const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
5959                                        "  gl_Position = g_in_position;" NL "}";
5960 
5961         const char *const glsl_gs =
5962             NL "layout(triangles) in;" NL "layout(triangle_strip, max_vertices = 3) out;" NL
5963                "layout(std430, binding = 1) buffer OutputBuffer {" NL "  vec4 g_output_buffer[];" NL "};" NL
5964                "void main() {" NL "  for (int i = 0; i < 3; ++i) {" NL
5965                "    const int idx = gl_PrimitiveIDIn * 3 + i;" NL "    g_output_buffer[idx] = gl_in[i].gl_Position;" NL
5966                "    gl_Position = g_output_buffer[idx];" NL "    EmitVertex();" NL "  }" NL "}";
5967 
5968         const char *const glsl_fs =
5969             NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
5970 
5971         m_program[0] = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
5972         glLinkProgram(m_program[0]);
5973         if (!CheckProgram(m_program[0]))
5974             return ERROR;
5975 
5976         m_program[1] = CreateProgram(glsl_vs, glsl_fs);
5977         glLinkProgram(m_program[1]);
5978         if (!CheckProgram(m_program[1]))
5979             return ERROR;
5980 
5981         /* vertex buffer */
5982         {
5983             const float data[] = {-1, -1, 1, -1, -1, 1, 1, 1};
5984             glGenBuffers(1, &m_vertex_buffer);
5985             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5986             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5987             glBindBuffer(GL_ARRAY_BUFFER, 0);
5988         }
5989 
5990         glGenBuffers(1, &m_storage_buffer);
5991         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer);
5992         glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
5993 
5994         glGenVertexArrays(2, m_vertex_array);
5995 
5996         glBindVertexArray(m_vertex_array[0]);
5997         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5998         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5999         glBindBuffer(GL_ARRAY_BUFFER, 0);
6000         glEnableVertexAttribArray(0);
6001         glBindVertexArray(0);
6002 
6003         glBindVertexArray(m_vertex_array[1]);
6004         glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
6005         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
6006         glBindBuffer(GL_ARRAY_BUFFER, 0);
6007         glEnableVertexAttribArray(0);
6008         glBindVertexArray(0);
6009 
6010         glClear(GL_COLOR_BUFFER_BIT);
6011         glUseProgram(m_program[0]);
6012         glBindVertexArray(m_vertex_array[0]);
6013         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6014         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6015         {
6016             return ERROR;
6017         }
6018 
6019         glClear(GL_COLOR_BUFFER_BIT);
6020         glUseProgram(m_program[1]);
6021         glBindVertexArray(m_vertex_array[1]);
6022         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
6023         glDrawArrays(GL_TRIANGLES, 0, 6);
6024         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6025         {
6026             return ERROR;
6027         }
6028 
6029         return NO_ERROR;
6030     }
6031 
Cleanup()6032     virtual long Cleanup()
6033     {
6034         glUseProgram(0);
6035         for (int i = 0; i < 2; ++i)
6036             glDeleteProgram(m_program[i]);
6037         glDeleteBuffers(1, &m_storage_buffer);
6038         glDeleteBuffers(1, &m_vertex_buffer);
6039         glDeleteVertexArrays(2, m_vertex_array);
6040         return NO_ERROR;
6041     }
6042 };
6043 //-----------------------------------------------------------------------------
6044 // 2.3.3 AdvancedWriteTessellation
6045 //-----------------------------------------------------------------------------
6046 
6047 class AdvancedWriteTessellation : public ShaderStorageBufferObjectBase
6048 {
6049     GLuint m_program;
6050     GLuint m_storage_buffer;
6051     GLuint m_counter_buffer;
6052     GLuint m_vertex_array;
6053     GLuint m_vertex_buffer;
6054 
Setup()6055     virtual long Setup()
6056     {
6057         m_program        = 0;
6058         m_storage_buffer = 0;
6059         m_counter_buffer = 0;
6060         m_vertex_array   = 0;
6061         m_vertex_buffer  = 0;
6062         return NO_ERROR;
6063     }
6064 
Run()6065     virtual long Run()
6066     {
6067         if (!SupportedInTES(1))
6068             return NOT_SUPPORTED;
6069 
6070         const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
6071                                        "  gl_Position = g_in_position;" NL "}";
6072 
6073         const char *const glsl_tes =
6074             NL "layout(quads) in;" NL "struct VertexData {" NL "  int valid;" NL "  vec4 position;" NL "};" NL
6075                "layout(std430, binding = 2) buffer VertexBuffer {" NL "  VertexData g_vertex_buffer[];" NL "};" NL
6076                "layout(binding = 2, offset = 0) uniform atomic_uint g_vertex_counter;" NL "void main() {" NL
6077                "  const uint idx = atomicCounterIncrement(g_vertex_counter);" NL
6078                "  vec4 p0 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);" NL
6079                "  vec4 p1 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);" NL
6080                "  vec4 p = mix(p0, p1, gl_TessCoord.y);" NL "  g_vertex_buffer[idx].position = p;" NL
6081                "  g_vertex_buffer[idx].valid = 1;" NL "  gl_Position = g_vertex_buffer[idx].position;" NL "}";
6082 
6083         const char *const glsl_fs =
6084             NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
6085 
6086         m_program = CreateProgram(glsl_vs, "", glsl_tes, "", glsl_fs);
6087         glLinkProgram(m_program);
6088         if (!CheckProgram(m_program))
6089             return ERROR;
6090 
6091         /* vertex buffer */
6092         {
6093             const float data[] = {-1, -1, 1, -1, 1, 1, -1, 1};
6094             glGenBuffers(1, &m_vertex_buffer);
6095             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6096             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6097             glBindBuffer(GL_ARRAY_BUFFER, 0);
6098         }
6099 
6100         glGenBuffers(1, &m_counter_buffer);
6101         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
6102         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
6103         uvec4 zero;
6104         glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
6105 
6106         struct
6107         {
6108             int valid;
6109             int pad[3];
6110             vec4 position;
6111         } data[6];
6112         deMemset((void *)data, 0, sizeof(data));
6113         glGenBuffers(1, &m_storage_buffer);
6114         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer);
6115         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6116 
6117         glGenVertexArrays(1, &m_vertex_array);
6118         glBindVertexArray(m_vertex_array);
6119         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6120         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6121         glBindBuffer(GL_ARRAY_BUFFER, 0);
6122         glEnableVertexAttribArray(0);
6123         glBindVertexArray(0);
6124 
6125         glClear(GL_COLOR_BUFFER_BIT);
6126         glUseProgram(m_program);
6127         glBindVertexArray(m_vertex_array);
6128         glPatchParameteri(GL_PATCH_VERTICES, 4);
6129         glDrawArrays(GL_PATCHES, 0, 4);
6130         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6131         {
6132             return ERROR;
6133         }
6134 
6135         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6136         glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6137         for (int i = 0; i < 4; ++i)
6138         {
6139             vec4 p = data[i].position;
6140             if (p[2] != 0.0f || p[3] != 1.0f)
6141                 return ERROR;
6142             if (data[i].valid != 1)
6143                 return ERROR;
6144         }
6145 
6146         return NO_ERROR;
6147     }
6148 
Cleanup()6149     virtual long Cleanup()
6150     {
6151         glPatchParameteri(GL_PATCH_VERTICES, 3);
6152         glUseProgram(0);
6153         glDeleteProgram(m_program);
6154         glDeleteBuffers(1, &m_storage_buffer);
6155         glDeleteBuffers(1, &m_counter_buffer);
6156         glDeleteBuffers(1, &m_vertex_buffer);
6157         glDeleteVertexArrays(1, &m_vertex_array);
6158         return NO_ERROR;
6159     }
6160 };
6161 
6162 //-----------------------------------------------------------------------------
6163 // 2.4.1 AdvancedIndirectAddressingCase1
6164 //-----------------------------------------------------------------------------
6165 class AdvancedIndirectAddressingCase1 : public ShaderStorageBufferObjectBase
6166 {
6167     GLuint m_program;
6168     GLuint m_storage_buffer[4];
6169     GLuint m_vertex_array;
6170     GLuint m_vertex_buffer;
6171     GLuint m_fbo, m_rt;
6172 
Setup()6173     virtual long Setup()
6174     {
6175         m_program = 0;
6176         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6177         m_vertex_array  = 0;
6178         m_vertex_buffer = 0;
6179         glGenFramebuffers(1, &m_fbo);
6180         glGenTextures(1, &m_rt);
6181         return NO_ERROR;
6182     }
6183 
Run()6184     virtual long Run()
6185     {
6186         if (!SupportedInVS(4))
6187             return NOT_SUPPORTED;
6188 
6189         const char *const glsl_vs =
6190             NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
6191                "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
6192                "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
6193                "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
6194                "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
6195                "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
6196                "  const uint mid = g_material_id[gl_InstanceID];" NL "  Material m = g_material[mid];" NL
6197                "  const uint tid = g_transform_id[gl_InstanceID];" NL "  vec2 t = g_transform.translation[tid];" NL
6198                "  gl_Position = vec4(g_in_position + t, 0, 1);" NL "  g_vs_out.color = m.color;" NL "}";
6199 
6200         const char *const glsl_fs =
6201             NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
6202                "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
6203 
6204         m_program = CreateProgram(glsl_vs, glsl_fs);
6205         glLinkProgram(m_program);
6206         if (!CheckProgram(m_program))
6207             return ERROR;
6208 
6209         glGenBuffers(4, m_storage_buffer);
6210 
6211         /* material buffer */
6212         {
6213             const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6214                                   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
6215             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6216             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6217         }
6218         /* material id buffer */
6219         {
6220             const unsigned int data[] = {2, 3, 0, 2};
6221             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6222             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6223         }
6224         /* transform buffer */
6225         {
6226             const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
6227             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6228             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6229         }
6230         /* transform id buffer */
6231         {
6232             const unsigned int data[] = {3, 1, 0, 2};
6233             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6234             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6235         }
6236 
6237         /* vertex buffer */
6238         {
6239             const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
6240             glGenBuffers(1, &m_vertex_buffer);
6241             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6242             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6243             glBindBuffer(GL_ARRAY_BUFFER, 0);
6244         }
6245 
6246         glBindTexture(GL_TEXTURE_2D, m_rt);
6247         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6248         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6249         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6250         glBindTexture(GL_TEXTURE_2D, 0);
6251         glViewport(0, 0, 100, 100);
6252         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6253         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6254 
6255         glGenVertexArrays(1, &m_vertex_array);
6256         glBindVertexArray(m_vertex_array);
6257         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6258         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6259         glBindBuffer(GL_ARRAY_BUFFER, 0);
6260         glEnableVertexAttribArray(0);
6261         glBindVertexArray(0);
6262 
6263         glClear(GL_COLOR_BUFFER_BIT);
6264         glUseProgram(m_program);
6265         glBindVertexArray(m_vertex_array);
6266         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6267 
6268         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
6269         {
6270             return ERROR;
6271         }
6272 
6273         /* update material id buffer with BufferSubData */
6274         {
6275             const unsigned int data[] = {3, 2, 1, 0};
6276             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6277             glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6278         }
6279 
6280         /* update transform id buffer with BufferData */
6281         {
6282             const unsigned int data[] = {0, 1, 2, 3};
6283             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6284             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6285         }
6286 
6287         glClear(GL_COLOR_BUFFER_BIT);
6288         glUseProgram(m_program);
6289         glBindVertexArray(m_vertex_array);
6290         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6291         if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
6292         {
6293             return ERROR;
6294         }
6295 
6296         return NO_ERROR;
6297     }
6298 
Cleanup()6299     virtual long Cleanup()
6300     {
6301         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6302         glUseProgram(0);
6303         glDeleteProgram(m_program);
6304         glDeleteBuffers(4, m_storage_buffer);
6305         glDeleteBuffers(1, &m_vertex_buffer);
6306         glDeleteVertexArrays(1, &m_vertex_array);
6307         glDeleteFramebuffers(1, &m_fbo);
6308         glDeleteTextures(1, &m_rt);
6309         return NO_ERROR;
6310     }
6311 };
6312 
6313 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
6314 {
6315     GLuint m_program;
6316     GLuint m_storage_buffer[5];
6317 
Setup()6318     virtual long Setup()
6319     {
6320         m_program = 0;
6321         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6322         return NO_ERROR;
6323     }
6324 
Run()6325     virtual long Run()
6326     {
6327         bool status = true;
6328 
6329         const char *const glsl_cs =
6330             NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
6331                "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
6332                "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
6333                "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
6334                "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
6335                "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[16];" NL "  vec2 pos[16];" NL
6336                "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
6337                "vec2(0.4f, 0.4f));" NL "void main() {" NL "  uint mid = g_material_id[gl_WorkGroupID.x];" NL
6338                "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_WorkGroupID.x];" NL
6339                "  vec2 t = g_transform.translation[tid];" NL
6340                "  pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
6341                "    = g_in_position[gl_LocalInvocationIndex] + t;" NL "  color[gl_LocalInvocationIndex + "
6342                "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
6343                "gl_WorkGroupSize.y] = m.color;" NL "}";
6344 
6345         m_program = CreateProgramCS(glsl_cs);
6346         glLinkProgram(m_program);
6347         if (!CheckProgram(m_program))
6348             return ERROR;
6349 
6350         glGenBuffers(5, m_storage_buffer);
6351 
6352         /* material buffer */
6353         {
6354             const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6355                                   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
6356             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6357             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6358         }
6359         /* material id buffer */
6360         {
6361             const unsigned int data[] = {2, 3, 0, 2};
6362             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6363             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6364         }
6365         /* transform buffer */
6366         {
6367             const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
6368             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6369             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6370         }
6371         /* transform id buffer */
6372         {
6373             const unsigned int data[] = {3, 1, 0, 2};
6374             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6375             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6376         }
6377 
6378         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6379         glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
6380 
6381         glUseProgram(m_program);
6382         glDispatchCompute(4, 1, 1);
6383         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6384         GLfloat *out_data =
6385             (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6386         if (!out_data)
6387             return ERROR;
6388         GLfloat expected[16 * 4 + 16 * 2] = {
6389             0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
6390             1.0f,  0.0f,  1.0f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,  0.0f,
6391             1.0f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
6392             0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,
6393             0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.1f,  0.1f,  0.9f,  0.1f,  0.1f,  0.9f,
6394             0.9f,  0.9f,  0.1f,  -0.9f, 0.9f,  -0.9f, 0.1f,  -0.1f, 0.9f,  -0.1f, -0.9f, -0.9f, -0.1f, -0.9f,
6395             -0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f,  -0.1f, 0.1f,  -0.9f, 0.9f,  -0.1f, 0.9f};
6396         for (int i = 0; i < 16; ++i)
6397         {
6398             if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
6399                 out_data[i * 4 + 2] != expected[i * 4 + 2])
6400             {
6401                 m_context.getTestContext().getLog()
6402                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6403                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6404                     << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << tcu::TestLog::EndMessage;
6405                 status = false;
6406             }
6407         }
6408         for (int i = 32; i < 32 + 16; ++i)
6409         {
6410             if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
6411                 fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
6412             {
6413                 m_context.getTestContext().getLog()
6414                     << tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
6415                     << ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1]
6416                     << tcu::TestLog::EndMessage;
6417                 status = false;
6418             }
6419         }
6420         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6421 
6422         /* update material id buffer with BufferSubData */
6423         {
6424             const unsigned int data[] = {3, 2, 1, 0};
6425             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6426             glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6427         }
6428 
6429         /* update transform id buffer with BufferData */
6430         {
6431             const unsigned int data[] = {0, 1, 2, 3};
6432             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6433             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6434         }
6435 
6436         glUseProgram(m_program);
6437         glDispatchCompute(4, 1, 1);
6438         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6439         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6440         GLfloat *out_data2 =
6441             (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6442         if (!out_data2)
6443             return ERROR;
6444         GLfloat expected2[16 * 4 + 16 * 2] = {
6445             1.0f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,  0.0f, 0.0f,  1.0f, 1.0f,  0.0f, 0.0f,
6446             0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 0.0f,  1.0f, 0.0f,
6447             0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,  0.0f, 0.0f,  0.0f, 1.0f,  0.0f, 0.0f,
6448             1.0f,  0.0f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f, 0.0f,  0.0f, 0.0f,  1.0f, 0.0f,  0.0f, 0.0f,
6449             -0.9f, -0.9f, -0.1f, -0.9f, -0.9f, -0.1f, -0.1f, -0.1f, 0.1f, -0.9f, 0.9f, -0.9f, 0.1f, -0.1f, 0.9f, -0.1f,
6450             -0.9f, 0.1f,  -0.1f, 0.1f,  -0.9f, 0.9f,  -0.1f, 0.9f,  0.1f, 0.1f,  0.9f, 0.1f,  0.1f, 0.9f,  0.9f, 0.9f};
6451         for (int i = 0; i < 16; ++i)
6452         {
6453             if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
6454                 out_data2[i * 4 + 2] != expected2[i * 4 + 2])
6455             {
6456                 m_context.getTestContext().getLog()
6457                     << tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
6458                     << ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
6459                     << expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << tcu::TestLog::EndMessage;
6460                 status = false;
6461             }
6462         }
6463         for (int i = 32; i < 32 + 16; ++i)
6464         {
6465             if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
6466                 fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
6467             {
6468                 m_context.getTestContext().getLog()
6469                     << tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
6470                     << ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1]
6471                     << tcu::TestLog::EndMessage;
6472                 status = false;
6473             }
6474         }
6475 
6476         if (status)
6477             return NO_ERROR;
6478         else
6479             return ERROR;
6480     }
6481 
Cleanup()6482     virtual long Cleanup()
6483     {
6484         glUseProgram(0);
6485         glDeleteProgram(m_program);
6486         glDeleteBuffers(5, m_storage_buffer);
6487         return NO_ERROR;
6488     }
6489 };
6490 //-----------------------------------------------------------------------------
6491 // 2.4.2 AdvancedIndirectAddressingCase2
6492 //-----------------------------------------------------------------------------
6493 
6494 class AdvancedIndirectAddressingCase2 : public ShaderStorageBufferObjectBase
6495 {
6496     GLuint m_program;
6497     GLuint m_storage_buffer[8];
6498     GLuint m_vertex_array;
6499     GLuint m_vertex_buffer;
6500     GLuint m_fbo, m_rt;
6501 
Setup()6502     virtual long Setup()
6503     {
6504         m_program = 0;
6505         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6506         m_vertex_array  = 0;
6507         m_vertex_buffer = 0;
6508         glGenFramebuffers(1, &m_fbo);
6509         glGenTextures(1, &m_rt);
6510         return NO_ERROR;
6511     }
6512 
Run()6513     virtual long Run()
6514     {
6515         if (!SupportedInVS(4))
6516             return NOT_SUPPORTED;
6517 
6518         const char *const glsl_vs =
6519             NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
6520                "  vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id = 2;" NL "void main() {" NL
6521                "  gl_Position = vec4(g_in_position + g_transform[g_transform_id].translation, 0, 1);" NL "}";
6522 
6523         const char *const glsl_fs =
6524             NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
6525                "  vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id = 1;" NL "void main() {" NL
6526                "  g_fs_out = vec4(g_material[g_material_id].color, 1);" NL "}";
6527         m_program = CreateProgram(glsl_vs, glsl_fs);
6528         glLinkProgram(m_program);
6529         if (!CheckProgram(m_program))
6530             return ERROR;
6531 
6532         glGenBuffers(8, m_storage_buffer);
6533 
6534         /* transform buffers */
6535         {
6536             const float data[4][2] = {{-0.5f, -0.5f}, {0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f}};
6537 
6538             for (GLuint i = 0; i < 4; ++i)
6539             {
6540                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6541                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6542             }
6543         }
6544         /* material buffers */
6545         {
6546             const float data[4][4] = {
6547                 {1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 0.0f, 0.0f}};
6548             for (GLuint i = 0; i < 4; ++i)
6549             {
6550                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6551                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6552             }
6553         }
6554 
6555         /* vertex buffer */
6556         {
6557             const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
6558             glGenBuffers(1, &m_vertex_buffer);
6559             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6560             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6561             glBindBuffer(GL_ARRAY_BUFFER, 0);
6562         }
6563 
6564         glBindTexture(GL_TEXTURE_2D, m_rt);
6565         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6566         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6567         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6568         glBindTexture(GL_TEXTURE_2D, 0);
6569         glViewport(0, 0, 100, 100);
6570         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6571         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6572 
6573         glGenVertexArrays(1, &m_vertex_array);
6574         glBindVertexArray(m_vertex_array);
6575         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6576         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6577         glBindBuffer(GL_ARRAY_BUFFER, 0);
6578         glEnableVertexAttribArray(1);
6579         glBindVertexArray(0);
6580 
6581         glUseProgram(m_program);
6582         glBindVertexArray(m_vertex_array);
6583 
6584         glClear(GL_COLOR_BUFFER_BIT);
6585         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6586         if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6587         {
6588             return ERROR;
6589         }
6590 
6591         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6592         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6593         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6594         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6595         {
6596             return ERROR;
6597         }
6598 
6599         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6600         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6601         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6602         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6603         {
6604             return ERROR;
6605         }
6606 
6607         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6608         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6609         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6610         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6611         {
6612             return ERROR;
6613         }
6614 
6615         // once again with only one validation at the end
6616         glClear(GL_COLOR_BUFFER_BIT);
6617         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6618         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6619         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6620 
6621         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6622         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6623         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6624 
6625         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6626         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6627         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6628 
6629         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6630         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6631         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6632         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6633 
6634         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6635         {
6636             return ERROR;
6637         }
6638         return NO_ERROR;
6639     }
6640 
Cleanup()6641     virtual long Cleanup()
6642     {
6643         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6644         glUseProgram(0);
6645         glDeleteProgram(m_program);
6646         glDeleteBuffers(8, m_storage_buffer);
6647         glDeleteBuffers(1, &m_vertex_buffer);
6648         glDeleteVertexArrays(1, &m_vertex_array);
6649         glDeleteFramebuffers(1, &m_fbo);
6650         glDeleteTextures(1, &m_rt);
6651         return NO_ERROR;
6652     }
6653 };
6654 
6655 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6656 {
6657     GLuint m_program;
6658     GLuint m_storage_buffer[5];
6659 
Setup()6660     virtual long Setup()
6661     {
6662         m_program = 0;
6663         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6664         return NO_ERROR;
6665     }
6666 
Run()6667     virtual long Run()
6668     {
6669         GLint blocksC;
6670         glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6671         if (blocksC < 8)
6672             return NOT_SUPPORTED;
6673         bool status = true;
6674 
6675         const char *const glsl_cs =
6676             NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL
6677                "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL
6678                "};" NL "uniform int g_material_id;" NL "void main() {" NL
6679                "  color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}";
6680 
6681         m_program = CreateProgramCS(glsl_cs);
6682         glLinkProgram(m_program);
6683         if (!CheckProgram(m_program))
6684             return ERROR;
6685 
6686         glGenBuffers(5, m_storage_buffer);
6687 
6688         /* material buffers */
6689         const float data[4][3] = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 0.0f}};
6690 
6691         for (GLuint i = 0; i < 4; ++i)
6692         {
6693             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6694             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6695         }
6696 
6697         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6698         glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6699 
6700         glUseProgram(m_program);
6701         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6702         glDispatchCompute(1, 1, 1);
6703         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6704         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6705         GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6706         if (!out_data)
6707             return ERROR;
6708         const float *expected = &data[1][0];
6709 
6710         for (int i = 0; i < 4; ++i)
6711         {
6712             if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6713                 out_data[i * 4 + 2] != expected[2])
6714             {
6715                 m_context.getTestContext().getLog()
6716                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6717                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6718                     << expected[2] << tcu::TestLog::EndMessage;
6719                 status = false;
6720             }
6721         }
6722         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6723         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6724         glDispatchCompute(1, 1, 1);
6725         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6726         out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6727         if (!out_data)
6728             return ERROR;
6729         expected = &data[3][0];
6730 
6731         for (int i = 0; i < 4; ++i)
6732         {
6733             if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6734                 out_data[i * 4 + 2] != expected[2])
6735             {
6736                 m_context.getTestContext().getLog()
6737                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6738                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6739                     << expected[2] << tcu::TestLog::EndMessage;
6740                 status = false;
6741             }
6742         }
6743 
6744         if (!status)
6745         {
6746             return ERROR;
6747         }
6748         return NO_ERROR;
6749     }
6750 
Cleanup()6751     virtual long Cleanup()
6752     {
6753         glUseProgram(0);
6754         glDeleteProgram(m_program);
6755         glDeleteBuffers(5, m_storage_buffer);
6756         return NO_ERROR;
6757     }
6758 };
6759 
6760 //-----------------------------------------------------------------------------
6761 // 2.5.1 AdvancedReadWriteCase1
6762 //-----------------------------------------------------------------------------
6763 class AdvancedReadWriteCase1 : public ShaderStorageBufferObjectBase
6764 {
6765     GLuint m_program;
6766     GLuint m_storage_buffer;
6767     GLuint m_vertex_array;
6768     GLuint m_vertex_buffer;
6769 
Setup()6770     virtual long Setup()
6771     {
6772         m_program        = 0;
6773         m_storage_buffer = 0;
6774         m_vertex_array   = 0;
6775         m_vertex_buffer  = 0;
6776         return NO_ERROR;
6777     }
6778 
Run()6779     virtual long Run()
6780     {
6781         if (!SupportedInVS(1))
6782             return NOT_SUPPORTED;
6783 
6784         const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6785                                        "  vec4 in_color;" NL "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6786                                        "  if (gl_VertexID == 0) {" NL "    g_buffer.out_color = g_buffer.in_color;" NL
6787                                        "    memoryBarrier();" NL "  }" NL "  gl_Position = g_in_position;" NL "}";
6788 
6789         const char *const glsl_fs =
6790             NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL "  vec4 in_color;" NL
6791                "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL "  g_fs_out = g_buffer.out_color;" NL "}";
6792 
6793         m_program = CreateProgram(glsl_vs, glsl_fs);
6794         glLinkProgram(m_program);
6795         if (!CheckProgram(m_program))
6796             return ERROR;
6797 
6798         glGenBuffers(1, &m_storage_buffer);
6799         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6800         glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6801         float *ptr = reinterpret_cast<float *>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
6802         if (!ptr)
6803             return ERROR;
6804         *ptr++ = 0.0f;
6805         *ptr++ = 1.0f;
6806         *ptr++ = 0.0f;
6807         *ptr++ = 1.0f;
6808         *ptr++ = 0.0f;
6809         *ptr++ = 0.0f;
6810         *ptr++ = 0.0f;
6811         *ptr++ = 0.0f;
6812         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6813 
6814         /* vertex buffer */
6815         {
6816             const float data[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6817             glGenBuffers(1, &m_vertex_buffer);
6818             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6819             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6820             glBindBuffer(GL_ARRAY_BUFFER, 0);
6821         }
6822 
6823         glGenVertexArrays(1, &m_vertex_array);
6824         glBindVertexArray(m_vertex_array);
6825         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6826         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6827         glBindBuffer(GL_ARRAY_BUFFER, 0);
6828         glEnableVertexAttribArray(0);
6829         glBindVertexArray(0);
6830 
6831         glClear(GL_COLOR_BUFFER_BIT);
6832         glUseProgram(m_program);
6833         glBindVertexArray(m_vertex_array);
6834         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6835         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6836         {
6837             return ERROR;
6838         }
6839 
6840         // update input color
6841         ptr = reinterpret_cast<float *>(
6842             glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6843         if (!ptr)
6844             return ERROR;
6845         *ptr++ = 1.0f;
6846         *ptr++ = 0.0f;
6847         *ptr++ = 1.0f;
6848         *ptr++ = 1.0f;
6849         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6850 
6851         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6852         if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(1.0f, 0.0f, 1.0f)))
6853         {
6854             return ERROR;
6855         }
6856 
6857         return NO_ERROR;
6858     }
6859 
Cleanup()6860     virtual long Cleanup()
6861     {
6862         glUseProgram(0);
6863         glDeleteProgram(m_program);
6864         glDeleteBuffers(1, &m_storage_buffer);
6865         glDeleteBuffers(1, &m_vertex_buffer);
6866         glDeleteVertexArrays(1, &m_vertex_array);
6867         return NO_ERROR;
6868     }
6869 };
6870 
6871 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6872 {
6873     GLuint m_program;
6874     GLuint m_storage_buffer;
6875 
Setup()6876     virtual long Setup()
6877     {
6878         m_program        = 0;
6879         m_storage_buffer = 0;
6880         return NO_ERROR;
6881     }
6882 
Run()6883     virtual long Run()
6884     {
6885         bool status = true;
6886 
6887         const char *const glsl_cs = NL
6888             "layout(local_size_x = 128) in;" NL "struct s {" NL "  int ene;" NL "  int due;" NL "  int like;" NL
6889             "  int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL "  s a[128];" NL "} g_buffer;" NL
6890             "void main() {" NL "  g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6891             "  groupMemoryBarrier();" NL "  barrier();" NL "  g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6892             "g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL "  groupMemoryBarrier();" NL "  barrier();" NL
6893             "  g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6894             "= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6895             "128u].like;" NL "}";
6896         m_program = CreateProgramCS(glsl_cs);
6897         glLinkProgram(m_program);
6898         if (!CheckProgram(m_program))
6899             return ERROR;
6900 
6901         glGenBuffers(1, &m_storage_buffer);
6902         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6903         GLint data[128 * 4];
6904         for (int i = 0; i < 128; ++i)
6905         {
6906             data[i * 4]     = i + 256;
6907             data[i * 4 + 1] = 0;
6908             data[i * 4 + 2] = 0;
6909             data[i * 4 + 3] = 0;
6910         }
6911         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6912 
6913         glUseProgram(m_program);
6914         glDispatchCompute(1, 1, 1);
6915         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6916         GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6917         if (!out_data)
6918             return ERROR;
6919         for (int i = 0; i < 128; ++i)
6920         {
6921             if (out_data[i * 4 + 3] != data[i * 4])
6922             {
6923                 m_context.getTestContext().getLog()
6924                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6925                     << ", but expected: " << data[i * 4] << " -> " << out_data[i * 4 + 1] << " -> "
6926                     << out_data[i * 4 + 2] << tcu::TestLog::EndMessage;
6927                 status = false;
6928             }
6929         }
6930         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6931         for (int i = 0; i < 128; ++i)
6932         {
6933             data[i * 4]     = i + 512;
6934             data[i * 4 + 1] = 0;
6935             data[i * 4 + 2] = 0;
6936             data[i * 4 + 3] = 0;
6937         }
6938         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6939 
6940         glDispatchCompute(1, 1, 1);
6941         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6942         out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6943         if (!out_data)
6944             return ERROR;
6945         for (int i = 0; i < 128; ++i)
6946         {
6947             if (out_data[i * 4 + 3] != data[i * 4])
6948             {
6949                 m_context.getTestContext().getLog()
6950                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6951                     << ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6952                 status = false;
6953             }
6954         }
6955         if (status)
6956             return NO_ERROR;
6957         else
6958             return ERROR;
6959     }
6960 
Cleanup()6961     virtual long Cleanup()
6962     {
6963         glUseProgram(0);
6964         glDeleteProgram(m_program);
6965         glDeleteBuffers(1, &m_storage_buffer);
6966         return NO_ERROR;
6967     }
6968 };
6969 //-----------------------------------------------------------------------------
6970 // 2.6.1 AdvancedUsageCase1
6971 //-----------------------------------------------------------------------------
6972 
6973 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6974 {
6975     GLuint m_program;
6976     GLuint m_storage_buffer[3];
6977     GLuint m_vertex_array;
6978     GLuint m_vertex_buffer;
6979     GLuint m_fbo, m_rt;
6980 
Setup()6981     virtual long Setup()
6982     {
6983         m_program = 0;
6984         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6985         m_vertex_array  = 0;
6986         m_vertex_buffer = 0;
6987         glGenFramebuffers(1, &m_fbo);
6988         glGenTextures(1, &m_rt);
6989         return NO_ERROR;
6990     }
6991 
Run()6992     virtual long Run()
6993     {
6994         if (!SupportedInVS(1))
6995             return NOT_SUPPORTED;
6996 
6997         const char *const glsl_vs =
6998             NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
6999                "out StageData {" NL "  flat int object_id;" NL "} g_vs_out;" NL
7000                "layout(binding = 0, std430) buffer TransformBuffer {" NL "  mat4 g_transform[];" NL "};" NL
7001                "void main() {" NL "  mat4 mvp = g_transform[g_object_id];" NL "  gl_Position = mvp * g_position;" NL
7002                "  g_vs_out.object_id = g_object_id;" NL "}";
7003 
7004         const char *const glsl_fs = NL
7005             "in StageData {" NL "  flat int object_id;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
7006             "struct Material {" NL "  vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
7007             "  Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
7008             "  int g_material_id[4];" NL "};" NL "void main() {" NL "  int mid = g_material_id[g_fs_in.object_id];" NL
7009             "  Material m = g_material[mid];" NL "  g_fs_out = vec4(m.color, 1);" NL "}";
7010 
7011         m_program = CreateProgram(glsl_vs, glsl_fs);
7012         glLinkProgram(m_program);
7013         if (!CheckProgram(m_program))
7014             return ERROR;
7015 
7016         glGenBuffers(3, m_storage_buffer);
7017 
7018         /* transform buffer */
7019         {
7020             mat4 data[] = {Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
7021                            Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f)};
7022             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7023             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7024         }
7025         /* material buffer */
7026         {
7027             vec4 data[] = {vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1)};
7028             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7029             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7030         }
7031         /* material id buffer */
7032         {
7033             int data[] = {0, 1, 2, 3};
7034             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7035             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7036         }
7037         /* vertex buffer */
7038         {
7039             struct
7040             {
7041                 vec2 position;
7042                 int object_id;
7043             } data[] = {{vec2(-0.4f, -0.4f), 0}, {vec2(0.4f, -0.4f), 0}, {vec2(-0.4f, 0.4f), 0}, {vec2(0.4f, 0.4f), 0},
7044                         {vec2(-0.4f, -0.4f), 1}, {vec2(0.4f, -0.4f), 1}, {vec2(-0.4f, 0.4f), 1}, {vec2(0.4f, 0.4f), 1},
7045                         {vec2(-0.4f, -0.4f), 2}, {vec2(0.4f, -0.4f), 2}, {vec2(-0.4f, 0.4f), 2}, {vec2(0.4f, 0.4f), 2},
7046                         {vec2(-0.4f, -0.4f), 3}, {vec2(0.4f, -0.4f), 3}, {vec2(-0.4f, 0.4f), 3}, {vec2(0.4f, 0.4f), 3}};
7047             glGenBuffers(1, &m_vertex_buffer);
7048             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7049             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7050             glBindBuffer(GL_ARRAY_BUFFER, 0);
7051         }
7052 
7053         glBindTexture(GL_TEXTURE_2D, m_rt);
7054         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7055         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7056         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
7057         glBindTexture(GL_TEXTURE_2D, 0);
7058         glViewport(0, 0, 100, 100);
7059         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
7060         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
7061 
7062         glGenVertexArrays(1, &m_vertex_array);
7063         glBindVertexArray(m_vertex_array);
7064         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7065         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
7066         glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void *>(sizeof(vec2)));
7067         glBindBuffer(GL_ARRAY_BUFFER, 0);
7068         glEnableVertexAttribArray(0);
7069         glEnableVertexAttribArray(1);
7070         glBindVertexArray(0);
7071 
7072         glClear(GL_COLOR_BUFFER_BIT);
7073         glUseProgram(m_program);
7074         glBindVertexArray(m_vertex_array);
7075         /* draw */
7076         {
7077             const GLint first[4]   = {0, 4, 8, 12};
7078             const GLsizei count[4] = {4, 4, 4, 4};
7079             glMultiDrawArrays(GL_TRIANGLE_STRIP, first, count, 4);
7080         }
7081         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
7082         {
7083             return ERROR;
7084         }
7085         return NO_ERROR;
7086     }
7087 
Cleanup()7088     virtual long Cleanup()
7089     {
7090         glViewport(0, 0, getWindowWidth(), getWindowHeight());
7091         glUseProgram(0);
7092         glDeleteProgram(m_program);
7093         glDeleteBuffers(3, m_storage_buffer);
7094         glDeleteBuffers(1, &m_vertex_buffer);
7095         glDeleteVertexArrays(1, &m_vertex_array);
7096         glDeleteFramebuffers(1, &m_fbo);
7097         glDeleteTextures(1, &m_rt);
7098         return NO_ERROR;
7099     }
7100 };
7101 //-----------------------------------------------------------------------------
7102 // 2.6.2 AdvancedUsageSync
7103 //-----------------------------------------------------------------------------
7104 
7105 class AdvancedUsageSync : public ShaderStorageBufferObjectBase
7106 {
7107     GLuint m_program;
7108     GLuint m_storage_buffer[7];
7109     GLuint m_vertex_array;
7110 
Setup()7111     virtual long Setup()
7112     {
7113         m_program = 0;
7114         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7115         m_vertex_array = 0;
7116         return NO_ERROR;
7117     }
7118 
Run()7119     virtual long Run()
7120     {
7121         if (!SupportedInVS(3))
7122             return NOT_SUPPORTED;
7123 
7124         const char *const glsl_vs =
7125             NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL "  int g_data0, g_inc0;" NL
7126                "  int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL
7127                "  int inc, data;" NL "} g_buffer12[2];" NL NL "void Modify(int path) {" NL "  if (path == 0) {" NL
7128                "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
7129                "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
7130                "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
7131                "  }" NL NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
7132                "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
7133                "void main() {" NL "  Modify(gl_VertexID);" NL "  gl_Position = vec4(0, 0, 0, 1);" NL "}";
7134 
7135         const char *glsl_fs =
7136             NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
7137                "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
7138                "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7139                "  int inc, data;" NL "} g_buffer56[2];" NL NL "void ModifyFS(int path) {" NL "  if (path == 0) {" NL
7140                "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7141                "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7142                "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
7143                "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7144                "  }" NL NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
7145                "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL
7146                "void main() {" NL "  atomicAdd(g_buffer3.data, 1);" NL "  ModifyFS(gl_PrimitiveID);" NL "}";
7147 
7148         m_program = CreateProgram(glsl_vs, glsl_fs);
7149         glLinkProgram(m_program);
7150         if (!CheckProgram(m_program))
7151             return ERROR;
7152 
7153         glGenVertexArrays(1, &m_vertex_array);
7154         glGenBuffers(7, m_storage_buffer);
7155 
7156         /* Buffer0 */
7157         {
7158             int data[4] = {0, 1, 0, 2};
7159             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7160             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7161         }
7162         /* Buffer1 */
7163         {
7164             int data[2] = {3, 1};
7165             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7166             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7167         }
7168         /* Buffer2 */
7169         {
7170             int data[2] = {2, 4};
7171             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7172             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7173         }
7174         /* Buffer3 */
7175         {
7176             int data[1] = {0};
7177             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7178             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7179         }
7180         /* Buffer4 */
7181         {
7182             int data[4] = {0, 1, 0, 2};
7183             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7184             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7185         }
7186         /* Buffer5 */
7187         {
7188             int data[2] = {3, 1};
7189             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7190             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7191         }
7192         /* Buffer6 */
7193         {
7194             int data[2] = {2, 4};
7195             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7196             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7197         }
7198 
7199         glUseProgram(m_program);
7200         glBindVertexArray(m_vertex_array);
7201 
7202         glDrawArrays(GL_POINTS, 0, 3);
7203         glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7204         glDrawArrays(GL_POINTS, 0, 3);
7205 
7206         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7207 
7208         /* Buffer0 */
7209         {
7210             const int ref_data[4] = {4, 1, 4, 2};
7211             int data[4];
7212             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7213             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7214             for (int i = 0; i < 4; ++i)
7215             {
7216                 if (data[i] != ref_data[i])
7217                 {
7218                     m_context.getTestContext().getLog()
7219                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7220                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7221                     return ERROR;
7222                 }
7223             }
7224         }
7225         /* Buffer1 */
7226         {
7227             const int ref_data[2] = {3, 5};
7228             int data[2];
7229             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7230             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7231             for (int i = 0; i < 2; ++i)
7232             {
7233                 if (data[i] != ref_data[i])
7234                 {
7235                     m_context.getTestContext().getLog()
7236                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7237                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7238                     return ERROR;
7239                 }
7240             }
7241         }
7242         /* Buffer2 */
7243         {
7244             const int ref_data[2] = {2, 10};
7245             int data[2];
7246             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7247             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7248             for (int i = 0; i < 2; ++i)
7249             {
7250                 if (data[i] != ref_data[i])
7251                 {
7252                     m_context.getTestContext().getLog()
7253                         << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7254                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7255                     return ERROR;
7256                 }
7257             }
7258         }
7259         /* Buffer3 */
7260         {
7261             const int ref_data[1] = {6};
7262             int data[1];
7263             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7264             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7265             for (int i = 0; i < 1; ++i)
7266             {
7267                 if (data[i] != ref_data[i])
7268                 {
7269                     m_context.getTestContext().getLog()
7270                         << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7271                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7272                     return ERROR;
7273                 }
7274             }
7275         }
7276         /* Buffer4 */
7277         {
7278             const int ref_data[4] = {4, 1, 4, 2};
7279             int data[4];
7280             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7281             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7282             for (int i = 0; i < 4; ++i)
7283             {
7284                 if (data[i] != ref_data[i])
7285                 {
7286                     m_context.getTestContext().getLog()
7287                         << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7288                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7289                     return ERROR;
7290                 }
7291             }
7292         }
7293         /* Buffer5 */
7294         {
7295             const int ref_data[2] = {3, 5};
7296             int data[2];
7297             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7298             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7299             for (int i = 0; i < 2; ++i)
7300             {
7301                 if (data[i] != ref_data[i])
7302                 {
7303                     m_context.getTestContext().getLog()
7304                         << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7305                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7306                     return ERROR;
7307                 }
7308             }
7309         }
7310         /* Buffer6 */
7311         {
7312             const int ref_data[2] = {2, 10};
7313             int data[2];
7314             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7315             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7316             for (int i = 0; i < 2; ++i)
7317             {
7318                 if (data[i] != ref_data[i])
7319                 {
7320                     m_context.getTestContext().getLog()
7321                         << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7322                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7323                     return ERROR;
7324                 }
7325             }
7326         }
7327 
7328         return NO_ERROR;
7329     }
7330 
Cleanup()7331     virtual long Cleanup()
7332     {
7333         glUseProgram(0);
7334         glDeleteProgram(m_program);
7335         glDeleteBuffers(7, m_storage_buffer);
7336         glDeleteVertexArrays(1, &m_vertex_array);
7337         return NO_ERROR;
7338     }
7339 };
7340 
7341 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
7342 {
7343     GLuint m_program;
7344     GLuint m_storage_buffer[7];
7345 
Setup()7346     virtual long Setup()
7347     {
7348         m_program = 0;
7349         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7350         return NO_ERROR;
7351     }
7352 
Run()7353     virtual long Run()
7354     {
7355         const char *const glsl_cs =
7356             NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
7357                "  int g_data0, g_inc0;" NL "  int g_data1, g_inc1;" NL "};" NL
7358                "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL "} g_buffer12[2];" NL
7359                "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
7360                "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
7361                "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7362                "  int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL "  if (path == 0) {" NL
7363                "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
7364                "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
7365                "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
7366                "  }" NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
7367                "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
7368                "void Modify2(int path) {" NL "  if (path == 0) {" NL
7369                "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7370                "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7371                "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
7372                "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7373                "  }" NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
7374                "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL NL
7375                "void main() {" NL "  Modify1(int(gl_WorkGroupID.z));" NL "  atomicAdd(g_buffer3.data, 1);" NL
7376                "  Modify2(int(gl_WorkGroupID.z));" NL "}";
7377 
7378         m_program = CreateProgramCS(glsl_cs);
7379         glLinkProgram(m_program);
7380         if (!CheckProgram(m_program))
7381             return ERROR;
7382 
7383         glGenBuffers(7, m_storage_buffer);
7384 
7385         /* Buffer0 */
7386         {
7387             int data[4] = {0, 1, 0, 2};
7388             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7389             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7390         }
7391         /* Buffer1 */
7392         {
7393             int data[2] = {3, 1};
7394             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7395             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7396         }
7397         /* Buffer2 */
7398         {
7399             int data[2] = {2, 4};
7400             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7401             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7402         }
7403         /* Buffer3 */
7404         {
7405             int data[1] = {0};
7406             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7407             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7408         }
7409         /* Buffer4 */
7410         {
7411             int data[4] = {0, 1, 0, 2};
7412             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7413             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7414         }
7415         /* Buffer5 */
7416         {
7417             int data[2] = {3, 1};
7418             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7419             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7420         }
7421         /* Buffer6 */
7422         {
7423             int data[2] = {2, 4};
7424             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7425             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7426         }
7427 
7428         glUseProgram(m_program);
7429 
7430         glDispatchCompute(1, 1, 3);
7431         glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7432         glDispatchCompute(1, 1, 3);
7433 
7434         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7435 
7436         /* Buffer0 */
7437         {
7438             const int ref_data[4] = {4, 1, 4, 2};
7439             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7440             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7441             if (!data)
7442                 return ERROR;
7443             for (int i = 0; i < 4; ++i)
7444             {
7445                 if (data[i] != ref_data[i])
7446                 {
7447                     m_context.getTestContext().getLog()
7448                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7449                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7450                     return ERROR;
7451                 }
7452             }
7453             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7454         }
7455         /* Buffer1 */
7456         {
7457             const int ref_data[2] = {3, 5};
7458             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7459             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7460             if (!data)
7461                 return ERROR;
7462             for (int i = 0; i < 2; ++i)
7463             {
7464                 if (data[i] != ref_data[i])
7465                 {
7466                     m_context.getTestContext().getLog()
7467                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7468                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7469                     return ERROR;
7470                 }
7471             }
7472             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7473         }
7474         /* Buffer2 */
7475         {
7476             const int ref_data[2] = {2, 10};
7477             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7478             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7479             if (!data)
7480                 return ERROR;
7481             for (int i = 0; i < 2; ++i)
7482             {
7483                 if (data[i] != ref_data[i])
7484                 {
7485                     m_context.getTestContext().getLog()
7486                         << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7487                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7488                     return ERROR;
7489                 }
7490             }
7491             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7492         }
7493         /* Buffer3 */
7494         {
7495             const int ref_data[1] = {6};
7496             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7497             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7498             if (!data)
7499                 return ERROR;
7500             for (int i = 0; i < 1; ++i)
7501             {
7502                 if (data[i] != ref_data[i])
7503                 {
7504                     m_context.getTestContext().getLog()
7505                         << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7506                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7507                     return ERROR;
7508                 }
7509             }
7510             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7511         }
7512         /* Buffer4 */
7513         {
7514             const int ref_data[4] = {4, 1, 4, 2};
7515             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7516             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7517             if (!data)
7518                 return ERROR;
7519             for (int i = 0; i < 4; ++i)
7520             {
7521                 if (data[i] != ref_data[i])
7522                 {
7523                     m_context.getTestContext().getLog()
7524                         << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7525                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7526                     return ERROR;
7527                 }
7528             }
7529             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7530         }
7531         /* Buffer5 */
7532         {
7533             const int ref_data[2] = {3, 5};
7534             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7535             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7536             if (!data)
7537                 return ERROR;
7538             for (int i = 0; i < 2; ++i)
7539             {
7540                 if (data[i] != ref_data[i])
7541                 {
7542                     m_context.getTestContext().getLog()
7543                         << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7544                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7545                     return ERROR;
7546                 }
7547             }
7548             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7549         }
7550         /* Buffer6 */
7551         {
7552             const int ref_data[2] = {2, 10};
7553             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7554             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7555             if (!data)
7556                 return ERROR;
7557             for (int i = 0; i < 2; ++i)
7558             {
7559                 if (data[i] != ref_data[i])
7560                 {
7561                     m_context.getTestContext().getLog()
7562                         << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7563                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7564                     return ERROR;
7565                 }
7566             }
7567             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7568         }
7569 
7570         return NO_ERROR;
7571     }
7572 
Cleanup()7573     virtual long Cleanup()
7574     {
7575         glUseProgram(0);
7576         glDeleteProgram(m_program);
7577         glDeleteBuffers(7, m_storage_buffer);
7578         return NO_ERROR;
7579     }
7580 };
7581 
7582 //-----------------------------------------------------------------------------
7583 // 2.6.3 AdvancedUsageOperators
7584 //-----------------------------------------------------------------------------
7585 class AdvancedUsageOperators : public ShaderStorageBufferObjectBase
7586 {
7587     GLuint m_program;
7588     GLuint m_storage_buffer[2];
7589     GLuint m_vertex_array;
7590 
Setup()7591     virtual long Setup()
7592     {
7593         m_program = 0;
7594         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7595         m_vertex_array = 0;
7596         return NO_ERROR;
7597     }
7598 
Run()7599     virtual long Run()
7600     {
7601         if (!SupportedInVS(2))
7602             return NOT_SUPPORTED;
7603 
7604         const char *const glsl_vs =
7605             NL "layout(std430, binding = 0) buffer Buffer0 {" NL "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL
7606                "layout(std430, binding = 1) buffer Buffer1 {" NL "  int i0;" NL "} g_buffer1;" NL
7607                "uniform int g_values[] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL "  g_o0 += g_i0;" NL
7608                "  g_o0 <<= 1;" NL "  g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL "  g_o0 *= g_i0;" NL
7609                "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7610                "  g_o0 &= g_buffer1.i0;" NL "}";
7611 
7612         m_program = CreateProgram(glsl_vs, "");
7613         glLinkProgram(m_program);
7614         if (!CheckProgram(m_program))
7615             return ERROR;
7616 
7617         glGenVertexArrays(1, &m_vertex_array);
7618         glGenBuffers(2, m_storage_buffer);
7619 
7620         /* Buffer0 */
7621         {
7622             int data[4] = {3, 5};
7623             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7624             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7625         }
7626         /* Buffer1 */
7627         {
7628             int data[1] = {0};
7629             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7630             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7631         }
7632 
7633         glEnable(GL_RASTERIZER_DISCARD);
7634         glUseProgram(m_program);
7635         glBindVertexArray(m_vertex_array);
7636         glDrawArrays(GL_POINTS, 0, 1);
7637         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7638 
7639         /* Buffer0 */
7640         {
7641             const int ref_data[2] = {3, 37};
7642             int data[4];
7643             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7644             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7645             for (int i = 0; i < 2; ++i)
7646             {
7647                 if (data[i] != ref_data[i])
7648                 {
7649                     m_context.getTestContext().getLog()
7650                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7651                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7652                     return ERROR;
7653                 }
7654             }
7655         }
7656         /* Buffer0 */
7657         {
7658             const int ref_data[1] = {0xff2f};
7659             int data[1];
7660             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7661             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7662             for (int i = 0; i < 1; ++i)
7663             {
7664                 if (data[i] != ref_data[i])
7665                 {
7666                     m_context.getTestContext().getLog()
7667                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7668                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7669                     return ERROR;
7670                 }
7671             }
7672         }
7673 
7674         return NO_ERROR;
7675     }
7676 
Cleanup()7677     virtual long Cleanup()
7678     {
7679         glDisable(GL_RASTERIZER_DISCARD);
7680         glUseProgram(0);
7681         glDeleteProgram(m_program);
7682         glDeleteBuffers(2, m_storage_buffer);
7683         glDeleteVertexArrays(1, &m_vertex_array);
7684         return NO_ERROR;
7685     }
7686 };
7687 
7688 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7689 {
7690     GLuint m_program;
7691     GLuint m_storage_buffer[2];
7692 
Setup()7693     virtual long Setup()
7694     {
7695         m_program = 0;
7696         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7697         return NO_ERROR;
7698     }
7699 
Run()7700     virtual long Run()
7701     {
7702         const char *const glsl_cs =
7703             NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7704                "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7705                "  int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7706                "  g_o0 += g_i0;" NL "  g_o0 <<= 1;" NL "  g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL "  g_o0 *= g_i0;" NL
7707                "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7708                "  g_o0 &= g_buffer1.i0;" NL "}";
7709 
7710         m_program = CreateProgramCS(glsl_cs);
7711         glLinkProgram(m_program);
7712         if (!CheckProgram(m_program))
7713             return ERROR;
7714 
7715         glGenBuffers(2, m_storage_buffer);
7716 
7717         /* Buffer0 */
7718         {
7719             int data[4] = {3, 5};
7720             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7721             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7722         }
7723         /* Buffer1 */
7724         {
7725             int data[1] = {0};
7726             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7727             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7728         }
7729 
7730         glUseProgram(m_program);
7731         glDispatchCompute(1, 1, 1);
7732         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7733 
7734         /* Buffer0 */
7735         {
7736             const int ref_data[2] = {3, 37};
7737             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7738             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7739             if (!data)
7740                 return ERROR;
7741             for (int i = 0; i < 2; ++i)
7742             {
7743                 if (data[i] != ref_data[i])
7744                 {
7745                     m_context.getTestContext().getLog()
7746                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7747                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7748                     return ERROR;
7749                 }
7750             }
7751             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7752         }
7753 
7754         return NO_ERROR;
7755     }
7756 
Cleanup()7757     virtual long Cleanup()
7758     {
7759         glUseProgram(0);
7760         glDeleteProgram(m_program);
7761         glDeleteBuffers(2, m_storage_buffer);
7762         return NO_ERROR;
7763     }
7764 };
7765 
7766 //-----------------------------------------------------------------------------
7767 // 2.7 AdvancedUnsizedArrayLength
7768 //-----------------------------------------------------------------------------
7769 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7770 {
7771     GLuint m_program;
7772     GLuint m_storage_buffer[5];
7773     GLuint m_vertex_array;
7774 
Setup()7775     virtual long Setup()
7776     {
7777         m_program = 0;
7778         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7779         m_vertex_array = 0;
7780         return NO_ERROR;
7781     }
7782 
Run()7783     virtual long Run()
7784     {
7785         if (!SupportedInVS(5))
7786             return NOT_SUPPORTED;
7787 
7788         const char *const glsl_vs =
7789             NL "layout(std430, binding = 0) readonly buffer Input0 {" NL "  int g_input0[];" NL "};" NL
7790                "layout(std430, binding = 1) readonly buffer Input1 {" NL "  int data[];" NL "} g_input1;" NL
7791                "layout(std430, binding = 2) readonly buffer Input23 {" NL "  int data[];" NL "} g_input23[2];" NL
7792                "layout(std430, binding = 4) buffer Output {" NL "  int g_length[4];" NL "  int g_length2;" NL "};" NL
7793                "void main() {" NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7794                "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7795                "  g_length2 = g_length.length();" NL "}";
7796 
7797         m_program = CreateProgram(glsl_vs, "");
7798         glLinkProgram(m_program);
7799         if (!CheckProgram(m_program))
7800             return ERROR;
7801 
7802         glGenVertexArrays(1, &m_vertex_array);
7803         glGenBuffers(5, m_storage_buffer);
7804 
7805         /* input 0 */
7806         {
7807             int data[7] = {1, 2, 3, 4, 5, 6, 7};
7808             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7809             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7810         }
7811         /* input 1 */
7812         {
7813             int data[5] = {1, 2, 3, 4, 5};
7814             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7815             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7816         }
7817         /* input 2 */
7818         {
7819             int data[3] = {1, 2, 3};
7820             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7821             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7822         }
7823         /* input 3 */
7824         {
7825             int data[4] = {1, 2, 3, 4};
7826             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7827             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7828         }
7829         /* output */
7830         {
7831             int data[5] = {0};
7832             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7833             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7834         }
7835 
7836         glEnable(GL_RASTERIZER_DISCARD);
7837         glUseProgram(m_program);
7838         glBindVertexArray(m_vertex_array);
7839         glDrawArrays(GL_POINTS, 0, 1);
7840 
7841         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7842 
7843         /* output */
7844         {
7845             int data[5];
7846             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7847             glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7848             bool status = true;
7849             if (data[0] != 7)
7850             {
7851                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 0 length is " << data[0]
7852                                                     << " should be 7." << tcu::TestLog::EndMessage;
7853                 status = false;
7854             }
7855             if (data[1] != 5)
7856             {
7857                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 1 length is " << data[1]
7858                                                     << " should be 5." << tcu::TestLog::EndMessage;
7859                 status = false;
7860             }
7861             if (data[2] != 3)
7862             {
7863                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 2 length is " << data[2]
7864                                                     << " should be 3." << tcu::TestLog::EndMessage;
7865                 status = false;
7866             }
7867             if (data[3] != 4)
7868             {
7869                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 3 length is " << data[3]
7870                                                     << " should be 4." << tcu::TestLog::EndMessage;
7871                 status = false;
7872             }
7873             if (data[4] != 4)
7874             {
7875                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 length is " << data[4]
7876                                                     << " should be 4." << tcu::TestLog::EndMessage;
7877                 status = false;
7878             }
7879             if (!status)
7880                 return ERROR;
7881         }
7882 
7883         return NO_ERROR;
7884     }
7885 
Cleanup()7886     virtual long Cleanup()
7887     {
7888         glDisable(GL_RASTERIZER_DISCARD);
7889         glUseProgram(0);
7890         glDeleteProgram(m_program);
7891         glDeleteBuffers(5, m_storage_buffer);
7892         glDeleteVertexArrays(1, &m_vertex_array);
7893         return NO_ERROR;
7894     }
7895 };
7896 
7897 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7898 {
7899     GLuint m_program;
7900     GLuint m_storage_buffer[8];
7901     GLuint m_vertex_array;
7902 
7903     virtual void SetPath() = 0;
7904 
Setup()7905     virtual long Setup()
7906     {
7907         m_program = 0;
7908         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7909         m_vertex_array = 0;
7910         return NO_ERROR;
7911     }
7912 
Cleanup()7913     virtual long Cleanup()
7914     {
7915         glUseProgram(0);
7916         glDeleteProgram(m_program);
7917         glDeleteBuffers(8, m_storage_buffer);
7918         if (stage != compute)
7919             glDeleteVertexArrays(1, &m_vertex_array);
7920         return NO_ERROR;
7921     }
7922 
BuildShaderPT(int stagept)7923     std::string BuildShaderPT(int stagept)
7924     {
7925         std::ostringstream os;
7926         if (stagept == vertex)
7927         {
7928             os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);";
7929         }
7930         if (stagept == fragment)
7931         {
7932             os << NL "void main() {";
7933         }
7934         os << NL "}";
7935         return os.str();
7936     }
7937 
BuildShader()7938     std::string BuildShader()
7939     {
7940         std::ostringstream os;
7941         std::string e[4][7] = {{"bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4"},
7942                                {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7943                                {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7944                                {"S0", "S1", "S2", "S2", "S4", "S5", "S6"}};
7945 
7946         std::string sd =
7947             NL "struct S0 {" NL "  float f;" NL "  int i;" NL "  uint ui;" NL "  bool b;" NL "};" NL "struct S1 {" NL
7948                "  ivec3 iv;" NL "  bvec2 bv;" NL "  vec4 v;" NL "  uvec2 uv;" NL "};" NL "struct S2 {" NL
7949                "  mat2x2 m22;" NL "  mat4x4 m44;" NL "  mat2x3 m23;" NL "  mat4x2 m42;" NL "  mat3x4 m34;" NL "};" NL
7950                "struct S4 {" NL "  float f[1];" NL "  int i[2];" NL "  uint ui[3];" NL "  bool b[4];" NL
7951                "  ivec3 iv[5];" NL "  bvec2 bv[6];" NL "  vec4  v[7];" NL "  uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7952                "  S0 s0;" NL "  S1 s1;" NL "  S2 s2;" NL "};" NL "struct S6 {" NL "  S4 s4[3];" NL "};";
7953 
7954         std::string lo   = "";
7955         std::string l[4] = {"std140", "std430", "shared", "packed"};
7956         lo += l[layout];
7957 
7958         if (etype == matrix_rm)
7959             lo += ", row_major";
7960 
7961         std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7962                            ((other_members) ? ("\n  " + e[etype][0] + " pad0;") : "") + NL "  " + e[etype][0] +
7963                            " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7964                            ((other_members) ? ("\n  " + e[etype][1] + " pad1;") : "") + NL "  " + e[etype][1] +
7965                            " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7966                            ((other_members) ? ("\n  " + e[etype][2] + " pad2;") : "") + NL "  " + e[etype][2] +
7967                            " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7968                            ((other_members) ? ("\n  " + e[etype][4] + " pad4;") : "") + NL "  " + e[etype][4] +
7969                            " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7970                            ((other_members) ? ("\n  " + e[etype][5] + " pad5;") : "") + NL "  " + e[etype][5] +
7971                            " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7972                            ((other_members) ? ("\n  " + e[etype][6] + " pad6;") : "") + NL "  " + e[etype][6] +
7973                            " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7974                            "  int g_length[];" NL "};";
7975 
7976         std::string expr =
7977             NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7978                "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7979                "  g_length[4] = g_output0.data.length();" NL "  g_length[5] = g_input4.data.length();" NL
7980                "  g_length[6] = g_output1.data.length();";
7981 
7982         std::string lastelemexpr =
7983             NL "  g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7984                "  g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7985 
7986         if (length_as_index)
7987             expr += lastelemexpr;
7988         if (stage == vertex)
7989         {
7990             os << decl << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" << expr;
7991         }
7992         if (stage == fragment)
7993         {
7994             os << NL << decl << NL "void main() {" << expr;
7995         }
7996         if (stage == compute)
7997         {
7998             os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7999         }
8000         os << NL "}";
8001         return os.str();
8002     }
8003 
Run()8004     virtual long Run()
8005     {
8006         const int kSize = 100000;
8007         const int kBufs = 8;
8008         SetPath();
8009         if (stage == vertex && !SupportedInVS(8))
8010             return NOT_SUPPORTED;
8011         GLint blocksC;
8012         glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
8013         GLint minA;
8014         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
8015         if (blocksC < kBufs)
8016             return NOT_SUPPORTED;
8017         if (stage == vertex)
8018         {
8019             std::string glsl_vs = BuildShader();
8020             std::string glsl_fs = BuildShaderPT(fragment);
8021             m_program           = CreateProgram(glsl_vs, glsl_fs);
8022         }
8023         else if (stage == fragment)
8024         {
8025             std::string glsl_vs = BuildShaderPT(vertex);
8026             std::string glsl_fs = BuildShader();
8027             m_program           = CreateProgram(glsl_vs, glsl_fs);
8028         }
8029         else
8030         { // compute
8031             std::string glsl_cs = BuildShader();
8032             m_program           = CreateProgramCS(glsl_cs);
8033         }
8034         glLinkProgram(m_program);
8035         if (!CheckProgram(m_program))
8036             return ERROR;
8037         glUseProgram(m_program);
8038 
8039         glGenBuffers(kBufs, m_storage_buffer);
8040         int sizes[kBufs] = {7, 5, 3, 4, 23, 123, 419, 8};
8041 
8042         int columns[4][kBufs] = {{1, 1, 1, 1, 1, 1, 1, 1},  // vector: 1 col
8043                                  {2, 3, 4, 4, 2, 3, 4, 1},  // mat: # of cols
8044                                  {2, 3, 4, 4, 3, 2, 2, 1},  // RM mat: # of rows
8045                                  {1, 1, 1, 1, 1, 1, 1, 1}}; // structure: not used
8046 
8047         int scalars[4][kBufs] = {{4, 4, 4, 4, 2, 2, 4, 1},  //vector: size
8048                                  {2, 4, 4, 4, 4, 2, 2, 1},  //matrix column_major: rows
8049                                  {2, 4, 4, 4, 2, 4, 4, 1},  //matrix row_major: columns
8050                                  {1, 1, 1, 1, 1, 1, 1, 1}}; //structure: not used
8051 
8052         int mindw[4][kBufs]     = {{3, 4, 3, 3, 2, 2, 4, 1}, // # of real 32bit items
8053                                    {4, 9, 16, 16, 6, 6, 8, 1},
8054                                    {4, 9, 16, 16, 6, 6, 8, 1},
8055                                    {4, 11, 35, 35, 81, 127, 381, 1}};
8056         int std430struct[kBufs] = {4, 16, 48, 48, 88, 68, 264, 1};
8057         int std140struct[kBufs] = {4, 16, 60, 60, 144, 80, 432, 1};
8058         int bufsize[kBufs][2]   = {{0}};
8059 
8060         std::vector<ivec4> data(kSize, ivec4(41));
8061         for (int i = 0; i < kBufs; ++i)
8062         {
8063             if (layout == std430)
8064             {
8065                 bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
8066                 if (etype == structure)
8067                 {
8068                     bufsize[i][1] = 4 * std430struct[i];
8069                 }
8070             }
8071             else if (layout == std140)
8072             {
8073                 bufsize[i][1] = 4 * columns[etype][i] * 4;
8074                 if (etype == structure)
8075                 {
8076                     bufsize[i][1] = 4 * std140struct[i];
8077                 }
8078             }
8079             else
8080             {
8081                 bufsize[i][1] = 4 * mindw[etype][i];
8082             }
8083             bufsize[i][0] = sizes[i] * bufsize[i][1];
8084             if (i == kBufs - 1 || bind_seq == bindbasebefore)
8085             { // never trim feedback storage
8086                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8087                 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8088             }
8089             else
8090             {
8091                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
8092                 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8093                 if (bind_seq == bindbaseafter)
8094                 {
8095                     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8096                 }
8097                 else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
8098                 {
8099                     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
8100                                       bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8101                 }
8102                 else
8103                 { // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
8104                     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
8105                                       bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8106                 }
8107             }
8108         }
8109 
8110         if (stage != compute)
8111         {
8112             glGenVertexArrays(1, &m_vertex_array);
8113             glBindVertexArray(m_vertex_array);
8114             glDrawArrays(GL_POINTS, 0, 1);
8115         }
8116         else
8117         {
8118             glDispatchCompute(1, 1, 1);
8119         }
8120         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8121 
8122         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
8123         int *dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
8124         if (!dataout)
8125             return ERROR;
8126         bool status = true;
8127         for (int i = 0; i < kBufs - 1; ++i)
8128         {
8129             if (other_members)
8130                 sizes[i] -= 1; // space consumed by a pad
8131             if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
8132                 sizes[i] -= 2; // space constrained by offset of range size
8133             if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
8134             {
8135                 m_context.getTestContext().getLog()
8136                     << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
8137                     << sizes[i] << tcu::TestLog::EndMessage;
8138                 status = false;
8139             }
8140             if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
8141             {
8142                 m_context.getTestContext().getLog()
8143                     << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
8144                     << " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
8145                 status = false;
8146             }
8147         }
8148         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8149 
8150         if (length_as_index)
8151         {
8152             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
8153             dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
8154             if (!dataout)
8155                 return ERROR;
8156             int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
8157             if (dataout[i] != 82)
8158             {
8159                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
8160                                                     << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8161                 status = false;
8162             }
8163             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8164             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
8165             dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
8166             if (!dataout)
8167                 return ERROR;
8168             i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
8169             if (dataout[i] != 82)
8170             {
8171                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
8172                                                     << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8173                 status = false;
8174             }
8175             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8176         }
8177 
8178         if (!status)
8179             return ERROR;
8180 
8181         return NO_ERROR;
8182     }
8183 
8184 public:
8185     int stage;
8186     int etype;
8187     int layout;
8188     bool other_members;
8189     int bind_seq;
8190     bool length_as_index;
8191 
AdvancedUnsizedArrayLength2()8192     AdvancedUnsizedArrayLength2()
8193         : m_program(0)
8194         , m_vertex_array(0)
8195         , stage(compute)
8196         , etype(vector)
8197         , layout(std430)
8198         , other_members(false)
8199         , bind_seq(bindbasebefore)
8200         , length_as_index(false)
8201     {
8202     }
8203 };
8204 
8205 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
8206 {
8207 public:
SetPath()8208     virtual void SetPath()
8209     {
8210         length_as_index = true;
8211     }
8212 };
8213 
8214 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
8215 {
8216 public:
SetPath()8217     virtual void SetPath()
8218     {
8219         bind_seq = bindbaseafter;
8220     }
8221 };
8222 
8223 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
8224 {
8225 public:
SetPath()8226     virtual void SetPath()
8227     {
8228         bind_seq = bindrangeoffset;
8229     }
8230 };
8231 
8232 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
8233 {
8234 public:
SetPath()8235     virtual void SetPath()
8236     {
8237         bind_seq = bindrangesize;
8238     }
8239 };
8240 
8241 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
8242 {
8243 public:
SetPath()8244     virtual void SetPath()
8245     {
8246         etype = vector;
8247     }
8248 };
8249 
8250 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
8251 {
8252 public:
SetPath()8253     virtual void SetPath()
8254     {
8255         etype = matrix_cm;
8256     }
8257 };
8258 
8259 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
8260 {
8261 public:
SetPath()8262     virtual void SetPath()
8263     {
8264         etype = matrix_rm;
8265     }
8266 };
8267 
8268 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
8269 {
8270 public:
SetPath()8271     virtual void SetPath()
8272     {
8273         etype = structure;
8274     }
8275 };
8276 
8277 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
8278 {
8279 public:
SetPath()8280     virtual void SetPath()
8281     {
8282         stage  = compute;
8283         layout = std140;
8284     }
8285 };
8286 
8287 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
8288 {
8289 public:
SetPath()8290     virtual void SetPath()
8291     {
8292         etype  = matrix_cm;
8293         layout = std140;
8294     }
8295 };
8296 
8297 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
8298 {
8299 public:
SetPath()8300     virtual void SetPath()
8301     {
8302         etype  = matrix_rm;
8303         layout = std140;
8304     }
8305 };
8306 
8307 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
8308 {
8309 public:
SetPath()8310     virtual void SetPath()
8311     {
8312         etype  = structure;
8313         layout = std140;
8314     }
8315 };
8316 
8317 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
8318 {
8319 public:
SetPath()8320     virtual void SetPath()
8321     {
8322         etype  = vector;
8323         layout = packed;
8324     }
8325 };
8326 
8327 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
8328 {
8329 public:
SetPath()8330     virtual void SetPath()
8331     {
8332         etype  = matrix_cm;
8333         layout = packed;
8334     }
8335 };
8336 
8337 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
8338 {
8339 public:
SetPath()8340     virtual void SetPath()
8341     {
8342         etype  = matrix_rm;
8343         layout = shared;
8344     }
8345 };
8346 
8347 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
8348 {
8349 public:
SetPath()8350     virtual void SetPath()
8351     {
8352         stage  = fragment;
8353         etype  = vector;
8354         layout = std430;
8355     }
8356 };
8357 
8358 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8359 {
8360 public:
SetPath()8361     virtual void SetPath()
8362     {
8363         stage         = fragment;
8364         etype         = matrix_cm;
8365         layout        = std430;
8366         other_members = true;
8367     }
8368 };
8369 
8370 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
8371 {
8372 public:
SetPath()8373     virtual void SetPath()
8374     {
8375         stage  = fragment;
8376         etype  = matrix_rm;
8377         layout = std140;
8378     }
8379 };
8380 
8381 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
8382 {
8383 public:
SetPath()8384     virtual void SetPath()
8385     {
8386         stage  = fragment;
8387         etype  = structure;
8388         layout = std140;
8389     }
8390 };
8391 
8392 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8393 {
8394 public:
SetPath()8395     virtual void SetPath()
8396     {
8397         stage         = vertex;
8398         etype         = vector;
8399         layout        = std430;
8400         other_members = true;
8401     }
8402 };
8403 
8404 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
8405 {
8406 public:
SetPath()8407     virtual void SetPath()
8408     {
8409         stage  = vertex;
8410         etype  = matrix_cm;
8411         layout = std140;
8412     }
8413 };
8414 
8415 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
8416 {
8417 public:
SetPath()8418     virtual void SetPath()
8419     {
8420         stage  = vertex;
8421         etype  = matrix_rm;
8422         layout = packed;
8423     }
8424 };
8425 
8426 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
8427 {
8428 public:
SetPath()8429     virtual void SetPath()
8430     {
8431         stage  = vertex;
8432         etype  = structure;
8433         layout = std140;
8434     }
8435 };
8436 
8437 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8438 {
8439 public:
SetPath()8440     virtual void SetPath()
8441     {
8442         etype         = vector;
8443         other_members = true;
8444     }
8445 };
8446 
8447 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8448 {
8449 public:
SetPath()8450     virtual void SetPath()
8451     {
8452         etype         = matrix_cm;
8453         other_members = true;
8454     }
8455 };
8456 
8457 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
8458 {
8459 public:
SetPath()8460     virtual void SetPath()
8461     {
8462         etype         = matrix_rm;
8463         layout        = std140;
8464         other_members = true;
8465     }
8466 };
8467 
8468 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
8469 {
8470 public:
SetPath()8471     virtual void SetPath()
8472     {
8473         etype         = structure;
8474         other_members = true;
8475     }
8476 };
8477 
8478 //-----------------------------------------------------------------------------
8479 // 2.8 AdvancedMatrix
8480 //-----------------------------------------------------------------------------
8481 
8482 class AdvancedMatrix : public ShaderStorageBufferObjectBase
8483 {
8484     GLuint m_program;
8485     GLuint m_storage_buffer[3];
8486     GLuint m_vertex_array;
8487     GLuint m_vertex_buffer;
8488     GLuint m_fbo, m_rt;
8489 
Setup()8490     virtual long Setup()
8491     {
8492         m_program = 0;
8493         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
8494         m_vertex_array  = 0;
8495         m_vertex_buffer = 0;
8496         glGenFramebuffers(1, &m_fbo);
8497         glGenTextures(1, &m_rt);
8498         return NO_ERROR;
8499     }
8500 
Run()8501     virtual long Run()
8502     {
8503         if (!SupportedInVS(2))
8504             return NOT_SUPPORTED;
8505 
8506         const char *const glsl_vs =
8507             NL "layout(location = 0) in vec4 g_position;" NL "out StageData {" NL "  flat int instance_id;" NL
8508                "} vs_out;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
8509                "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
8510                "layout(binding = 1, std430) readonly buffer Buffer1 {" NL "  mat4 color;" NL "} g_buffer1;" NL
8511                "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8512                "  gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
8513                "  g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
8514                "  if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL "    g_data0[1][1] = 1.0;" NL
8515                "    g_data0[g_index1][g_index2] += 3.0;" NL "  }" NL "  memoryBarrier();" NL
8516                "  vs_out.instance_id = gl_InstanceID;" NL "}";
8517 
8518         const char *const glsl_fs =
8519             NL "in StageData {" NL "  flat int instance_id;" NL "} fs_in;" NL
8520                "layout(location = 0) out vec4 g_ocolor;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL
8521                "  mat3x4 g_transform[4];" NL "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
8522                "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8523                "  if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
8524                "  else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
8525                "  else g_ocolor = vec4(g_color[fs_in.instance_id], 1);" NL "}";
8526 
8527         m_program = CreateProgram(glsl_vs, glsl_fs);
8528         glLinkProgram(m_program);
8529         if (!CheckProgram(m_program))
8530             return ERROR;
8531 
8532         glGenBuffers(3, m_storage_buffer);
8533 
8534         /* transform buffer */
8535         {
8536             float data[48 + 16 + 12 + 16] = {
8537                 1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f,
8538                 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,  1.0f, 0.0f, 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.5f,
8539                 0.0f, 0.0f, 1.0f, 0.0f,  1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
8540             };
8541             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8542             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8543         }
8544         /* transform buffer */
8545         {
8546             float data[16] = {
8547                 1.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.5f,
8548             };
8549             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8550             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8551         }
8552         /* vertex buffer */
8553         {
8554             float data[8] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
8555             glGenBuffers(1, &m_vertex_buffer);
8556             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8557             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8558             glBindBuffer(GL_ARRAY_BUFFER, 0);
8559         }
8560 
8561         glBindTexture(GL_TEXTURE_2D, m_rt);
8562         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8563         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8564         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8565         glBindTexture(GL_TEXTURE_2D, 0);
8566         glViewport(0, 0, 100, 100);
8567         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8568         glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
8569 
8570         glGenVertexArrays(1, &m_vertex_array);
8571         glBindVertexArray(m_vertex_array);
8572         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8573         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8574         glBindBuffer(GL_ARRAY_BUFFER, 0);
8575         glEnableVertexAttribArray(0);
8576         glBindVertexArray(0);
8577 
8578         glClear(GL_COLOR_BUFFER_BIT);
8579         glUseProgram(m_program);
8580         glBindVertexArray(m_vertex_array);
8581         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8582 
8583         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8584         {
8585             return ERROR;
8586         }
8587         return NO_ERROR;
8588     }
8589 
Cleanup()8590     virtual long Cleanup()
8591     {
8592         glViewport(0, 0, getWindowWidth(), getWindowHeight());
8593         glUseProgram(0);
8594         glDeleteProgram(m_program);
8595         glDeleteBuffers(3, m_storage_buffer);
8596         glDeleteBuffers(1, &m_vertex_buffer);
8597         glDeleteVertexArrays(1, &m_vertex_array);
8598         glDeleteFramebuffers(1, &m_fbo);
8599         glDeleteTextures(1, &m_rt);
8600         return NO_ERROR;
8601     }
8602 };
8603 
8604 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8605 {
8606     GLuint m_program;
8607     GLuint m_storage_buffer;
8608 
Setup()8609     virtual long Setup()
8610     {
8611         m_program        = 0;
8612         m_storage_buffer = 0;
8613         return NO_ERROR;
8614     }
8615 
Run()8616     virtual long Run()
8617     {
8618         bool status = true;
8619         const char *const glsl_cs =
8620             NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL "  mat4x3 dst4x3;" NL
8621                "  mat4 dst4;" NL "  mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8622                "void main() {" NL "  b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8623                "  b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8624                "  b.dst4[g_index2][g_index1] = 17.0;" NL "  b.dst4[g_index2][g_index1] += 6.0;" NL
8625                "  b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL "  b.dst4[3][1] = b.src4[3][1];" NL "}";
8626         m_program = CreateProgramCS(glsl_cs);
8627         glLinkProgram(m_program);
8628         if (!CheckProgram(m_program))
8629             return ERROR;
8630 
8631         glGenBuffers(1, &m_storage_buffer);
8632         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8633         GLfloat data[16 + 16 + 16];
8634         for (int i = 0; i < 32; ++i)
8635             data[i] = 0.0f;
8636         for (int i = 32; i < 48; ++i)
8637             data[i] = (GLfloat)i;
8638         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8639 
8640         glUseProgram(m_program);
8641         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8642         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8643         glDispatchCompute(1, 1, 1);
8644         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8645         GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8646         if (!out_data)
8647             return ERROR;
8648 
8649         GLfloat expected[32] = {
8650             32.0f, 33.0f, 34.0f, 0.0f, 39.0f, 39.0f, 36.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f, 0.0f, 0.0f,  0.0f, 0.0f,
8651 
8652             0.0f,  0.0f,  0.0f,  0.0f, 0.0f,  0.0f,  0.0f,  0.0f, 0.0f, 23.0f, 0.0f, 0.0f, 7.0f, 45.0f, 0.0f, 0.0f};
8653         for (int i = 0; i < 32; ++i)
8654         {
8655             if (out_data[i] != expected[i])
8656             {
8657                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8658                                                     << ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8659                 status = false;
8660             }
8661         }
8662         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8663         if (status)
8664             return NO_ERROR;
8665         else
8666             return ERROR;
8667     }
8668 
Cleanup()8669     virtual long Cleanup()
8670     {
8671         glUseProgram(0);
8672         glDeleteProgram(m_program);
8673         glDeleteBuffers(1, &m_storage_buffer);
8674         return NO_ERROR;
8675     }
8676 };
8677 //-----------------------------------------------------------------------------
8678 // 4.1.1 NegativeAPIBind
8679 //-----------------------------------------------------------------------------
8680 
8681 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8682 {
Run()8683     virtual long Run()
8684     {
8685         GLint bindings;
8686         GLint alignment;
8687         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8688         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8689 
8690         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8691         if (glGetError() != GL_INVALID_VALUE)
8692         {
8693             m_context.getTestContext().getLog()
8694                 << tcu::TestLog::Message
8695                 << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8696                    "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8697                    "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8698                 << tcu::TestLog::EndMessage;
8699             return ERROR;
8700         }
8701 
8702         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8703         if (glGetError() != GL_INVALID_VALUE)
8704         {
8705             m_context.getTestContext().getLog()
8706                 << tcu::TestLog::Message
8707                 << "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8708                    "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8709                    "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8710                 << tcu::TestLog::EndMessage;
8711             return ERROR;
8712         }
8713 
8714         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 0, alignment - 1, 0);
8715         if (glGetError() != GL_INVALID_VALUE)
8716         {
8717             m_context.getTestContext().getLog()
8718                 << tcu::TestLog::Message
8719                 << "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8720                    "SHADER_STORAGE_BUFFER and <offset> is not a multiple of the value of\n"
8721                    "SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."
8722                 << tcu::TestLog::EndMessage;
8723             return ERROR;
8724         }
8725 
8726         return NO_ERROR;
8727     }
8728 };
8729 //-----------------------------------------------------------------------------
8730 // 4.1.2 NegativeAPIBlockBinding
8731 //-----------------------------------------------------------------------------
8732 
8733 class NegativeAPIBlockBinding : public ShaderStorageBufferObjectBase
8734 {
Run()8735     virtual long Run()
8736     {
8737         if (!SupportedInVS(1))
8738             return NOT_SUPPORTED;
8739         GLint bindings;
8740         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8741 
8742         const char *const glsl_vs =
8743             "#version 430 core" NL "buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8744         const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8745         glShaderSource(sh, 1, &glsl_vs, NULL);
8746         glCompileShader(sh);
8747 
8748         const GLuint p = glCreateProgram();
8749         glAttachShader(p, sh);
8750         glDeleteShader(sh);
8751         glLinkProgram(p);
8752 
8753         glShaderStorageBlockBinding(p, 0, bindings);
8754         if (glGetError() != GL_INVALID_VALUE)
8755         {
8756             m_context.getTestContext().getLog()
8757                 << tcu::TestLog::Message
8758                 << "An INVALID_VALUE error is generated if storageBlockBinding is\n"
8759                    "greater than or equal to the value of MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8760                 << tcu::TestLog::EndMessage;
8761             glDeleteProgram(p);
8762             return ERROR;
8763         }
8764 
8765         glShaderStorageBlockBinding(p, 1, 0);
8766         if (glGetError() != GL_INVALID_VALUE)
8767         {
8768             m_context.getTestContext().getLog()
8769                 << tcu::TestLog::Message
8770                 << "An INVALID_VALUE error is generated if storageBlockIndex is not an\n"
8771                    "active shader storage block index in program."
8772                 << tcu::TestLog::EndMessage;
8773             glDeleteProgram(p);
8774             return ERROR;
8775         }
8776 
8777         glShaderStorageBlockBinding(0, 0, 0);
8778         if (glGetError() != GL_INVALID_VALUE)
8779         {
8780             m_context.getTestContext().getLog() << tcu::TestLog::Message
8781                                                 << "An INVALID_VALUE error is generated if program is not the name of "
8782                                                    "either a program or shader object."
8783                                                 << tcu::TestLog::EndMessage;
8784             glDeleteProgram(p);
8785             return ERROR;
8786         }
8787 
8788         glShaderStorageBlockBinding(sh, 0, 0);
8789         if (glGetError() != GL_INVALID_OPERATION)
8790         {
8791             m_context.getTestContext().getLog()
8792                 << tcu::TestLog::Message
8793                 << "An INVALID_OPERATION error is generated if program is the name of a shader object."
8794                 << tcu::TestLog::EndMessage;
8795             glDeleteProgram(p);
8796             return ERROR;
8797         }
8798 
8799         glDeleteProgram(p);
8800         return NO_ERROR;
8801     }
8802 };
8803 //-----------------------------------------------------------------------------
8804 // 4.2.1 NegativeGLSLCompileTime
8805 //-----------------------------------------------------------------------------
8806 
8807 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8808 {
Shader1(int binding)8809     static std::string Shader1(int binding)
8810     {
8811         std::stringstream ss;
8812         ss << NL "layout(binding = " << binding
8813            << ") buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8814         return ss.str();
8815     }
8816 
Shader2(int binding)8817     static std::string Shader2(int binding)
8818     {
8819         std::stringstream ss;
8820         ss << NL "layout(binding = " << binding
8821            << ") buffer Buffer {" NL "  int x;" NL "} g_array[4];" NL "void main() {" NL "  g_array[0].x = 0;" NL
8822               "  g_array[1].x = 0;" NL "  g_array[2].x = 0;" NL "  g_array[3].x = 0;" NL "}";
8823         return ss.str();
8824     }
8825 
Run()8826     virtual long Run()
8827     {
8828         GLint bindings;
8829         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8830 
8831         //  initialization of buffer block member 'x' not allowed
8832         if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL "  x = 0;" NL "}"))
8833             return ERROR;
8834 
8835         //  syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8836         if (!Compile(Shader1(-1)))
8837             return ERROR;
8838         //  invalid value 96 for layout specifier 'binding'
8839         if (!Compile(Shader1(bindings)))
8840             return ERROR;
8841 
8842         //  invalid value 98 for layout specifier 'binding'
8843         if (!Compile(Shader2(bindings - 2)))
8844             return ERROR;
8845 
8846         //  OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8847         if (!Compile(NL "buffer int x;" NL "void main() {" NL "  x = 0;" NL "}"))
8848             return ERROR;
8849 
8850         // OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8851         if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL "  y = 0;" NL "  buffer int x = 0;" NL "}"))
8852             return ERROR;
8853 
8854         //  OpenGL does not allow a parameter to be a buffer
8855         if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL "  atomicAdd(a, 1);" NL "}" NL
8856                         "void main() {" NL "  Modify(y);" NL "}"))
8857             return ERROR;
8858 
8859         //  layout specifier 'std430', incompatible with 'uniform blocks'
8860         if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8861                         "  y = x;" NL "}"))
8862             return ERROR;
8863 
8864         //  unknown layout specifier 'std430'
8865         if (!Compile(NL "buffer SSBO {" NL "  layout(std430) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8866             return ERROR;
8867 
8868         //  unknown layout specifier 'binding = 1'
8869         if (!Compile(NL "buffer SSBO {" NL "  layout(binding = 1) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL
8870                         "}"))
8871             return ERROR;
8872 
8873         //  OpenGL does not allow writing to readonly variable 'x'
8874         if (!Compile(NL "readonly buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8875             return ERROR;
8876 
8877         //  OpenGL does not allow reading writeonly variable 'y'
8878         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "writeonly buffer SSBO2 {" NL "  int y;" NL "};" NL
8879                         "void main() {" NL "  x = y;" NL "}"))
8880             return ERROR;
8881 
8882         //  OpenGL does not allow writing to readonly variable 'z'
8883         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "buffer SSBO2 {" NL "  writeonly int y;" NL
8884                         "  readonly int z;" NL "};" NL "void main() {" NL "  x = y;" NL "  z = 0;" NL "}"))
8885             return ERROR;
8886 
8887         //  OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8888         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "readonly buffer SSBO2 {" NL "  writeonly int y;" NL
8889                         "};" NL "void main() {" NL "  x = y;" NL "}"))
8890             return ERROR;
8891 
8892         // ["layout(binding = 1) buffer;" should cause compile-time error
8893         if (!Compile(NL "layout(binding = 1) buffer;" NL "buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL
8894                         "  x = 0;" NL "}"))
8895             return ERROR;
8896 
8897         // ["  atomicAdd(y, 2);"  should cause compile-time error
8898         if (!Compile(NL "buffer Buffer { int x; };" NL "int y;" NL "void main() {" NL "  atomicAdd(x, 1);" NL
8899                         "  atomicAdd(y, 2);" //
8900                      NL "}"))
8901             return ERROR;
8902 
8903         if (!Compile( // can't construct vector from an array
8904                 NL "buffer b {" NL "  vec4 x[10];" NL "};" NL "void main() {" NL "  vec4 y = vec4(x);" NL "}"))
8905             return ERROR;
8906 
8907         return NO_ERROR;
8908     }
8909 
Compile(const std::string & source)8910     bool Compile(const std::string &source)
8911     {
8912         const char *const csVer  = "#version 430 core";
8913         const char *const src[2] = {csVer, source.c_str()};
8914         const GLuint sh          = glCreateShader(GL_FRAGMENT_SHADER);
8915         glShaderSource(sh, 2, src, NULL);
8916         glCompileShader(sh);
8917 
8918         GLchar log[1024];
8919         glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8920         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8921                                             << log << tcu::TestLog::EndMessage;
8922 
8923         GLint status;
8924         glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8925         glDeleteShader(sh);
8926 
8927         if (status == GL_TRUE)
8928         {
8929             m_context.getTestContext().getLog()
8930                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8931             return false;
8932         }
8933 
8934         return true;
8935     }
8936 };
8937 
8938 //-----------------------------------------------------------------------------
8939 // 4.2.2 NegativeGLSLLinkTime
8940 //-----------------------------------------------------------------------------
8941 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8942 {
Run()8943     virtual long Run()
8944     {
8945         //   declaration of "x" conflicts with previous declaration at 0(4)
8946         //   declaration of "Buffer" conflicts with previous declaration at 0(4)
8947         if (!Link("#version 430 core" NL "buffer Buffer { int x; };" NL "void Run();" NL "void main() {" NL
8948                   "  Run();" NL "  x += 2;" NL "}",
8949                   "#version 430 core" NL "buffer Buffer { uint x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8950             return ERROR;
8951 
8952         //  declaration of "Buffer" conflicts with previous declaration at 0(4)
8953         if (!Link("#version 430 core" NL "buffer Buffer { int x; int y; };" NL "void Run();" NL "void main() {" NL
8954                   "  Run();" NL "  x += 2;" NL "}",
8955                   "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8956             return ERROR;
8957 
8958         //  declaration of "Buffer" conflicts with previous declaration at 0(4)
8959         if (!Link("#version 430 core" NL "buffer Buffer { int y; };" NL "void Run();" NL "void main() {" NL
8960                   "  Run();" NL "  y += 2;" NL "}",
8961                   "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8962             return ERROR;
8963 
8964         //  declaration of "g_buffer" conflicts with previous declaration at 0(4)
8965         //  declaration of "Buffer" conflicts with previous declaration at 0(4)
8966         if (!Link("#version 430 core" NL "buffer Buffer { int x; } g_buffer[2];" NL "void Run();" NL "void main() {" NL
8967                   "  Run();" NL "  g_buffer[0].x += 2;" NL "}",
8968                   "#version 430 core" NL "buffer Buffer { int x; } g_buffer[3];" NL "void Run() {" NL
8969                   "  g_buffer[1].x += 3;" NL "}"))
8970             return ERROR;
8971 
8972         return NO_ERROR;
8973     }
8974 
Link(const std::string & cs0,const std::string & cs1)8975     bool Link(const std::string &cs0, const std::string &cs1)
8976     {
8977         const GLuint p = glCreateProgram();
8978 
8979         /* shader 0 */
8980         {
8981             GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8982             glAttachShader(p, sh);
8983             glDeleteShader(sh);
8984             const char *const src = cs0.c_str();
8985             glShaderSource(sh, 1, &src, NULL);
8986             glCompileShader(sh);
8987 
8988             GLint status;
8989             glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8990             if (status == GL_FALSE)
8991             {
8992                 glDeleteProgram(p);
8993                 m_context.getTestContext().getLog()
8994                     << tcu::TestLog::Message << "VS0 compilation should be ok." << tcu::TestLog::EndMessage;
8995                 return false;
8996             }
8997         }
8998         /* shader 1 */
8999         {
9000             GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
9001             glAttachShader(p, sh);
9002             glDeleteShader(sh);
9003             const char *const src = cs1.c_str();
9004             glShaderSource(sh, 1, &src, NULL);
9005             glCompileShader(sh);
9006 
9007             GLint status;
9008             glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
9009             if (status == GL_FALSE)
9010             {
9011                 glDeleteProgram(p);
9012                 m_context.getTestContext().getLog()
9013                     << tcu::TestLog::Message << "VS1 compilation should be ok." << tcu::TestLog::EndMessage;
9014                 return false;
9015             }
9016         }
9017 
9018         glLinkProgram(p);
9019 
9020         GLchar log[1024];
9021         glGetProgramInfoLog(p, sizeof(log), NULL, log);
9022         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
9023                                             << log << tcu::TestLog::EndMessage;
9024 
9025         GLint status;
9026         glGetProgramiv(p, GL_LINK_STATUS, &status);
9027         glDeleteProgram(p);
9028 
9029         if (status == GL_TRUE)
9030         {
9031             m_context.getTestContext().getLog()
9032                 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
9033             return false;
9034         }
9035 
9036         return true;
9037     }
9038 };
9039 
9040 } // anonymous namespace
9041 
ShaderStorageBufferObjectTests(deqp::Context & context)9042 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context &context)
9043     : TestCaseGroup(context, "shader_storage_buffer_object", "")
9044 {
9045 }
9046 
~ShaderStorageBufferObjectTests(void)9047 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
9048 {
9049 }
9050 
init()9051 void ShaderStorageBufferObjectTests::init()
9052 {
9053     using namespace deqp;
9054 
9055     addChild(new TestSubcase(m_context, "basic-basic", TestSubcase::Create<BasicBasic>));
9056     addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
9057     addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
9058     addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
9059     addChild(new TestSubcase(m_context, "basic-syntax", TestSubcase::Create<BasicSyntax>));
9060     addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
9061     addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
9062     addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
9063     addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
9064     addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
9065     addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
9066     addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
9067     addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
9068     addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
9069     addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
9070     addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
9071     addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
9072     addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
9073     addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
9074     addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
9075     addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
9076     addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
9077     addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
9078     addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
9079     addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
9080     addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
9081     addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
9082     addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
9083     addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
9084     addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
9085     addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
9086     addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
9087     addChild(new TestSubcase(m_context, "basic-atomic-case1", TestSubcase::Create<BasicAtomicCase1>));
9088     addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
9089     addChild(new TestSubcase(m_context, "basic-atomic-case2", TestSubcase::Create<BasicAtomicCase2>));
9090     addChild(new TestSubcase(m_context, "basic-atomic-case3", TestSubcase::Create<BasicAtomicCase3>));
9091     addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
9092     addChild(new TestSubcase(m_context, "basic-atomic-case4", TestSubcase::Create<BasicAtomicCase4>));
9093     addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
9094     addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
9095     addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
9096     addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
9097     addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
9098     addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
9099     addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
9100     addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
9101     addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
9102     addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
9103     addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
9104     addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
9105     addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
9106     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
9107                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
9108     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
9109                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
9110     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
9111                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
9112     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
9113                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
9114     addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
9115                              TestSubcase::Create<BasicMatrixOperationsCase1VS>));
9116     addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
9117                              TestSubcase::Create<BasicMatrixOperationsCase1CS>));
9118     addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
9119                              TestSubcase::Create<BasicMatrixOperationsCase2VS>));
9120     addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
9121                              TestSubcase::Create<BasicMatrixOperationsCase2CS>));
9122     addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
9123                              TestSubcase::Create<BasicMatrixOperationsCase3VS>));
9124     addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
9125                              TestSubcase::Create<BasicMatrixOperationsCase3CS>));
9126     addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
9127                              TestSubcase::Create<BasicMatrixOperationsCase4VS>));
9128     addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
9129                              TestSubcase::Create<BasicMatrixOperationsCase4CS>));
9130     addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
9131                              TestSubcase::Create<BasicMatrixOperationsCase5VS>));
9132     addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
9133                              TestSubcase::Create<BasicMatrixOperationsCase5CS>));
9134     addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
9135                              TestSubcase::Create<BasicMatrixOperationsCase6VS>));
9136     addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
9137                              TestSubcase::Create<BasicMatrixOperationsCase6CS>));
9138     addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
9139                              TestSubcase::Create<BasicMatrixOperationsCase7VS>));
9140     addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
9141                              TestSubcase::Create<BasicMatrixOperationsCase7CS>));
9142     addChild(new TestSubcase(m_context, "basic-noBindingLayout", TestSubcase::Create<BasicNoBindingLayout>));
9143     addChild(new TestSubcase(m_context, "basic-readonly-writeonly", TestSubcase::Create<BasicReadonlyWriteonly>));
9144     addChild(new TestSubcase(m_context, "basic-name-match", TestSubcase::Create<BasicNameMatch>));
9145     addChild(new TestSubcase(m_context, "advanced-switchBuffers", TestSubcase::Create<AdvancedSwitchBuffers>));
9146     addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
9147     addChild(new TestSubcase(m_context, "advanced-switchPrograms", TestSubcase::Create<AdvancedSwitchPrograms>));
9148     addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
9149     addChild(new TestSubcase(m_context, "advanced-write-fragment", TestSubcase::Create<AdvancedWriteFragment>));
9150     addChild(new TestSubcase(m_context, "advanced-write-geometry", TestSubcase::Create<AdvancedWriteGeometry>));
9151     addChild(new TestSubcase(m_context, "advanced-write-tessellation", TestSubcase::Create<AdvancedWriteTessellation>));
9152     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1",
9153                              TestSubcase::Create<AdvancedIndirectAddressingCase1>));
9154     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
9155                              TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
9156     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2",
9157                              TestSubcase::Create<AdvancedIndirectAddressingCase2>));
9158     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
9159                              TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
9160     addChild(new TestSubcase(m_context, "advanced-readWrite-case1", TestSubcase::Create<AdvancedReadWriteCase1>));
9161     addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
9162     addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
9163     addChild(new TestSubcase(m_context, "advanced-usage-sync", TestSubcase::Create<AdvancedUsageSync>));
9164     addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
9165     addChild(new TestSubcase(m_context, "advanced-usage-operators", TestSubcase::Create<AdvancedUsageOperators>));
9166     addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
9167     addChild(
9168         new TestSubcase(m_context, "advanced-unsizedArrayLength", TestSubcase::Create<AdvancedUnsizedArrayLength>));
9169     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
9170                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
9171     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
9172                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
9173     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
9174                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
9175     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
9176                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
9177     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
9178                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
9179     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
9180                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
9181     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
9182                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
9183     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
9184                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
9185     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
9186                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
9187     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
9188                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
9189     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
9190                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
9191     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
9192                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
9193     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
9194                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
9195     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
9196                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
9197     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
9198                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
9199     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
9200                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
9201     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
9202                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
9203     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
9204                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
9205     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
9206                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
9207     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
9208                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
9209     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
9210                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
9211     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
9212                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
9213     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
9214                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
9215 
9216     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
9217                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
9218 
9219     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
9220                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
9221 
9222     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
9223                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
9224 
9225     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
9226                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
9227 
9228     addChild(new TestSubcase(m_context, "advanced-matrix", TestSubcase::Create<AdvancedMatrix>));
9229     addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
9230     addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
9231     addChild(new TestSubcase(m_context, "negative-api-blockBinding", TestSubcase::Create<NegativeAPIBlockBinding>));
9232     addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
9233     addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
9234 }
9235 
9236 } // namespace gl4cts
9237