1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cES31CompatibilityTests.hpp"
25 #include "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 
35 namespace es31compatibility
36 {
37 using namespace glw;
38 
39 namespace
40 {
41 
42 typedef tcu::Vec2 vec2;
43 typedef tcu::Vec3 vec3;
44 typedef tcu::Vec4 vec4;
45 typedef tcu::IVec4 ivec4;
46 typedef tcu::UVec4 uvec4;
47 typedef tcu::Mat4 mat4;
48 
49 enum ShaderStage
50 {
51     vertex,
52     fragment,
53     compute
54 };
55 enum BufferLayout
56 {
57     std140,
58     std430,
59     shared,
60     packed
61 };
62 enum ElementType
63 {
64     vector,
65     matrix_cm,
66     matrix_rm,
67     structure
68 };
69 enum BindingSeq
70 {
71     bindbasebefore,
72     bindbaseafter,
73     bindrangeoffset,
74     bindrangesize
75 };
76 
77 const char *const kGLSLVer = "#version 310 es" NL "precision highp float;" NL "precision highp int;";
78 
79 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
80 {
Title()81     virtual std::string Title()
82     {
83         return "";
84     }
85 
Purpose()86     virtual std::string Purpose()
87     {
88         return "";
89     }
90 
Method()91     virtual std::string Method()
92     {
93         return "";
94     }
95 
PassCriteria()96     virtual std::string PassCriteria()
97     {
98         return "";
99     }
100 
101 public:
IsVSFSAvailable(int requiredVS,int requiredFS)102     bool IsVSFSAvailable(int requiredVS, int requiredFS)
103     {
104         GLint blocksVS, blocksFS;
105         glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
106         glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
107         if (blocksVS >= requiredVS && blocksFS >= requiredFS)
108             return true;
109         else
110         {
111             std::ostringstream reason;
112             reason << "Required " << requiredVS << " VS storage blocks but only " << blocksVS << " available."
113                    << std::endl
114                    << "Required " << requiredFS << " FS storage blocks but only " << blocksFS << " available."
115                    << std::endl;
116             OutputNotSupported(reason.str());
117             return false;
118         }
119     }
120 
getWindowWidth()121     int getWindowWidth()
122     {
123         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
124         return renderTarget.getWidth();
125     }
126 
getWindowHeight()127     int getWindowHeight()
128     {
129         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
130         return renderTarget.getHeight();
131     }
132 
CheckProgram(GLuint program)133     bool CheckProgram(GLuint program)
134     {
135         GLint status;
136         glGetProgramiv(program, GL_LINK_STATUS, &status);
137 
138         if (status == GL_FALSE)
139         {
140             GLint attached_shaders;
141             glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
142 
143             if (attached_shaders > 0)
144             {
145                 std::vector<GLuint> shaders(attached_shaders);
146                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
147 
148                 for (GLint i = 0; i < attached_shaders; ++i)
149                 {
150                     GLenum type;
151                     glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint *>(&type));
152                     switch (type)
153                     {
154                     case GL_VERTEX_SHADER:
155                         m_context.getTestContext().getLog()
156                             << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
157                         break;
158                     case GL_FRAGMENT_SHADER:
159                         m_context.getTestContext().getLog()
160                             << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
161                         break;
162                     case GL_COMPUTE_SHADER:
163                         m_context.getTestContext().getLog()
164                             << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
165                         break;
166                     default:
167                         m_context.getTestContext().getLog()
168                             << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
169                     }
170                     GLint length;
171                     glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
172                     if (length > 0)
173                     {
174                         std::vector<GLchar> source(length);
175                         glGetShaderSource(shaders[i], length, NULL, &source[0]);
176                         m_context.getTestContext().getLog()
177                             << tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
178                     }
179                     glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
180                     if (length > 0)
181                     {
182                         std::vector<GLchar> log(length);
183                         glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
184                         m_context.getTestContext().getLog()
185                             << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
186                     }
187                 }
188             }
189             GLint length;
190             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
191             if (length > 0)
192             {
193                 std::vector<GLchar> log(length);
194                 glGetProgramInfoLog(program, length, NULL, &log[0]);
195                 m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
196             }
197         }
198 
199         return status == GL_TRUE ? true : false;
200     }
201 
CreateProgram(const std::string & vs,const std::string & fs)202     GLuint CreateProgram(const std::string &vs, const std::string &fs)
203     {
204         const GLuint p = glCreateProgram();
205 
206         if (!vs.empty())
207         {
208             const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
209             glAttachShader(p, sh);
210             glDeleteShader(sh);
211             const char *const src[2] = {kGLSLVer, vs.c_str()};
212             glShaderSource(sh, 2, src, NULL);
213             glCompileShader(sh);
214         }
215         if (!fs.empty())
216         {
217             const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
218             glAttachShader(p, sh);
219             glDeleteShader(sh);
220             const char *const src[2] = {kGLSLVer, fs.c_str()};
221             glShaderSource(sh, 2, src, NULL);
222             glCompileShader(sh);
223         }
224 
225         return p;
226     }
CreateProgramCS(const std::string & cs)227     GLuint CreateProgramCS(const std::string &cs)
228     {
229         const GLuint p = glCreateProgram();
230 
231         if (!cs.empty())
232         {
233             const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
234             glAttachShader(p, sh);
235             glDeleteShader(sh);
236             const char *const src[2] = {kGLSLVer, cs.c_str()};
237             glShaderSource(sh, 2, src, NULL);
238             glCompileShader(sh);
239         }
240         return p;
241     }
242 
BuildShaderProgram(GLenum type,const std::string & source)243     GLuint BuildShaderProgram(GLenum type, const std::string &source)
244     {
245         const char *const src[2] = {kGLSLVer, source.c_str()};
246         return glCreateShaderProgramv(type, 2, src);
247     }
248 
ColorEqual(int x,int y,const vec3 & c0,const vec3 & expected,const vec3 & epsilon,const vec3 & color_max)249     bool ColorEqual(int x, int y, const vec3 &c0, const vec3 &expected, const vec3 &epsilon, const vec3 &color_max)
250     {
251         bool status = true;
252         if (fabs(c0[0] / color_max[0] - expected[0]) > epsilon[0])
253             status = false;
254         if (fabs(c0[1] / color_max[1] - expected[1]) > epsilon[1])
255             status = false;
256         if (fabs(c0[2] / color_max[2] - expected[2]) > epsilon[2])
257             status = false;
258 
259         if (!status)
260             m_context.getTestContext().getLog()
261                 << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << " " << y << "). Color is ("
262                 << c0[0] / color_max[0] << " " << c0[1] / color_max[1] << " " << c0[2] / color_max[2]
263                 << "). Color should be (" << expected[0] << " " << expected[1] << " " << expected[2] << ")."
264                 << tcu::TestLog::EndMessage;
265         return status;
266     }
267 
CheckFB(vec3 expected)268     bool CheckFB(vec3 expected)
269     {
270         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
271         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
272         vec3 g_color_eps = vec3(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
273                                 1.f / (float)(1 << pixelFormat.blueBits));
274         vec3 g_color_max = vec3(255);
275         std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4);
276         int fb_w = getWindowWidth();
277         int fb_h = getWindowHeight();
278         glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
279         for (GLint i = 0, y = 0; y < fb_h; ++y)
280             for (GLint x = 0; x < fb_w; ++x, i += 4)
281             {
282                 if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] ||
283                     fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] ||
284                     fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2])
285                 {
286                     m_context.getTestContext().getLog()
287                         << tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << " " << y
288                         << "). Color is (" << fb[i + 0] / g_color_max[0] << " " << fb[i + 1] / g_color_max[1] << " "
289                         << fb[i + 2] / g_color_max[2] << "). Color should be (" << expected[0] << " " << expected[1]
290                         << " " << expected[2] << ")." << tcu::TestLog::EndMessage;
291                     return false;
292                 }
293             }
294         return true;
295     }
296 
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)297     bool ValidateWindow4Quads(const vec3 &lb, const vec3 &rb, const vec3 &rt, const vec3 &lt, int *bad_pixels = NULL)
298     {
299         const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
300         const tcu::PixelFormat &pixelFormat   = renderTarget.getPixelFormat();
301         vec3 g_color_eps = vec3(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
302                                 1.f / (float)(1 << pixelFormat.blueBits));
303         vec3 g_color_max = vec3(255);
304 
305         const int width  = 100;
306         const int height = 100;
307         std::vector<GLubyte> fb(width * height * 4);
308         glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
309 
310         bool status = true;
311         int bad     = 0;
312 
313         // left-bottom quad
314         for (int y = 10, i = (100 * 10 + 10) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
315         {
316             for (int x = 10; x < width / 2 - 10; ++x, i += 4)
317             {
318                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
319                 if (!ColorEqual(x, y, c, lb, g_color_eps, g_color_max))
320                 {
321                     status = false;
322                     bad++;
323                 }
324             }
325         }
326         if (!status)
327         {
328             m_context.getTestContext().getLog()
329                 << tcu::TestLog::Message << "Left-bottom quad checking failed. Bad pixels: " << bad
330                 << tcu::TestLog::EndMessage;
331             //return status;
332         }
333         // right-bottom quad
334         for (int y = 10, i = (100 * 10 + 60) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
335         {
336             for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
337             {
338                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
339                 if (!ColorEqual(x, y, c, rb, g_color_eps, g_color_max))
340                 {
341                     status = false;
342                     bad++;
343                 }
344             }
345         }
346         if (!status)
347         {
348             m_context.getTestContext().getLog()
349                 << tcu::TestLog::Message << "right-bottom quad checking failed. Bad pixels: " << bad
350                 << tcu::TestLog::EndMessage;
351             //return status;
352         }
353         // right-top quad
354         for (int y = height / 2 + 10, i = (100 * 60 + 60) * 4; y < height - 10; ++y, i += 70 * 4)
355         {
356             for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
357             {
358                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
359                 if (!ColorEqual(x, y, c, rt, g_color_eps, g_color_max))
360                 {
361                     status = false;
362                     bad++;
363                 }
364             }
365         }
366         if (!status)
367         {
368             m_context.getTestContext().getLog()
369                 << tcu::TestLog::Message << "right-top quad checking failed. Bad pixels: " << bad
370                 << tcu::TestLog::EndMessage;
371             //return status;
372         }
373         // left-top quad
374         for (int y = height / 2 + 10, i = (100 * 60 + 10) * 4; y < height - 10; ++y, i += 70 * 4)
375         {
376             for (int x = 10; x < width / 2 - 10; ++x, i += 4)
377             {
378                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
379                 if (!ColorEqual(x, y, c, lt, g_color_eps, g_color_max))
380                 {
381                     status = false;
382                     bad++;
383                 }
384             }
385         }
386         if (!status)
387         {
388             m_context.getTestContext().getLog()
389                 << tcu::TestLog::Message << "left-top quad checking failed. Bad pixels: " << bad
390                 << tcu::TestLog::EndMessage;
391             //return status;
392         }
393         // middle horizontal line should be black
394         for (int y = height / 2 - 2, i = (100 * 48) * 4; y < height / 2 + 2; ++y)
395         {
396             for (int x = 0; x < width; ++x, i += 4)
397             {
398                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
399                 if (!ColorEqual(x, y, c, vec3(0), g_color_eps, g_color_max))
400                 {
401                     status = false;
402                     bad++;
403                 }
404             }
405         }
406         if (!status)
407         {
408             m_context.getTestContext().getLog()
409                 << tcu::TestLog::Message << "middle horizontal line checking failed. Bad pixels: " << bad
410                 << tcu::TestLog::EndMessage;
411             //return status;
412         }
413         // middle vertical line should be black
414         for (int y = 0, i = 48 * 4; y < height; ++y, i += 96 * 4)
415         {
416             for (int x = width / 2 - 2; x < width / 2 + 2; ++x, i += 4)
417             {
418                 const vec3 c = vec3(fb[i], fb[i + 1], fb[i + 2]);
419                 if (!ColorEqual(x, y, c, vec3(0), g_color_eps, g_color_max))
420                 {
421                     status = false;
422                     bad++;
423                 }
424             }
425         }
426         if (!status)
427         {
428             m_context.getTestContext().getLog()
429                 << tcu::TestLog::Message << "middle vertical line checking failed. Bad pixels: " << bad
430                 << tcu::TestLog::EndMessage;
431             //return status;
432         }
433 
434         if (bad_pixels)
435             *bad_pixels = bad;
436         m_context.getTestContext().getLog()
437             << tcu::TestLog::Message << "Bad pixels: " << (bad_pixels == NULL ? 0 : *bad_pixels)
438             << ", counted bad: " << bad << tcu::TestLog::EndMessage;
439         return status;
440     }
441 
Translation(float tx,float ty,float tz)442     const mat4 Translation(float tx, float ty, float tz)
443     {
444         float d[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, tx, ty, tz, 1.0f};
445         return mat4(d);
446     }
447 
GLenumToString(GLenum e)448     const char *GLenumToString(GLenum e)
449     {
450         switch (e)
451         {
452         case GL_SHADER_STORAGE_BUFFER_BINDING:
453             return "GL_SHADER_STORAGE_BUFFER_BINDING";
454         case GL_SHADER_STORAGE_BUFFER_START:
455             return "GL_SHADER_STORAGE_BUFFER_START";
456         case GL_SHADER_STORAGE_BUFFER_SIZE:
457             return "GL_SHADER_STORAGE_BUFFER_SIZE";
458         case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
459             return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
460         case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
461             return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
462         case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
463             return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
464         case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
465             return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
466         case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
467             return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
468         case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
469             return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
470         case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
471             return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
472         case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
473             return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
474 
475         default:
476             assert(0);
477             break;
478         }
479         return NULL;
480     }
481 };
482 
483 //-----------------------------------------------------------------------------
484 // 1.1 BasicBasic
485 //-----------------------------------------------------------------------------
486 class BasicBasicVS : public ShaderStorageBufferObjectBase
487 {
488     GLuint m_program;
489     GLuint m_buffer;
490     GLuint m_vertex_array;
491 
Setup()492     virtual long Setup()
493     {
494         m_program      = 0;
495         m_buffer       = 0;
496         m_vertex_array = 0;
497         return NO_ERROR;
498     }
499 
Run()500     virtual long Run()
501     {
502         if (!IsVSFSAvailable(1, 0))
503             return NOT_SUPPORTED;
504 
505         const char *const glsl_vs =
506             NL "layout(std430, binding = 1) buffer InputBuffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL
507                "void main() {" NL "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}";
508         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
509                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
510         m_program = CreateProgram(glsl_vs, glsl_fs);
511         glLinkProgram(m_program);
512         if (!CheckProgram(m_program))
513             return ERROR;
514 
515         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};
516         glGenBuffers(1, &m_buffer);
517         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
518         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
519         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
520 
521         glGenVertexArrays(1, &m_vertex_array);
522         glBindVertexArray(m_vertex_array);
523 
524         glUseProgram(m_program);
525         glClear(GL_COLOR_BUFFER_BIT);
526         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer);
527         glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);
528         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
529 
530         if (!CheckFB(vec3(0, 1, 0)))
531             return ERROR;
532         else
533             return NO_ERROR;
534     }
535 
Cleanup()536     virtual long Cleanup()
537     {
538         glUseProgram(0);
539         glDeleteProgram(m_program);
540         glDeleteBuffers(1, &m_buffer);
541         glDeleteVertexArrays(1, &m_vertex_array);
542         return NO_ERROR;
543     }
544 };
545 
546 class BasicBasicCS : public ShaderStorageBufferObjectBase
547 {
548     GLuint m_program;
549     GLuint m_buffer;
550 
Setup()551     virtual long Setup()
552     {
553         m_program = 0;
554         m_buffer  = 0;
555         return NO_ERROR;
556     }
557 
Run()558     virtual long Run()
559     {
560         const char *const glsl_cs = NL "layout(local_size_x = 1) in;" NL "buffer Buffer {" NL "  int result;" NL "};" NL
561                                        "void main() {" NL "  result = 7;" NL "}";
562         m_program = CreateProgramCS(glsl_cs);
563         glLinkProgram(m_program);
564         if (!CheckProgram(m_program))
565             return ERROR;
566 
567         glGenBuffers(1, &m_buffer);
568         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
569         glBufferData(GL_SHADER_STORAGE_BUFFER, 4, 0, GL_STATIC_READ);
570         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
571 
572         glUseProgram(m_program);
573         glDispatchCompute(1, 1, 1);
574         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
575 
576         GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
577         if (!out_data)
578             return ERROR;
579         if (*out_data == 7)
580             return NO_ERROR;
581         else
582             return ERROR;
583     }
584 
Cleanup()585     virtual long Cleanup()
586     {
587         glUseProgram(0);
588         glDeleteProgram(m_program);
589         glDeleteBuffers(1, &m_buffer);
590         return NO_ERROR;
591     }
592 };
593 
594 //-----------------------------------------------------------------------------
595 // 1.2 BasicMax
596 //-----------------------------------------------------------------------------
597 class BasicMax : public ShaderStorageBufferObjectBase
598 {
Check(GLenum e,GLint64 value,bool max_value)599     bool Check(GLenum e, GLint64 value, bool max_value)
600     {
601         GLint i;
602         GLint64 i64;
603         GLfloat f;
604         GLboolean b;
605 
606         glGetIntegerv(e, &i);
607         glGetInteger64v(e, &i64);
608         glGetFloatv(e, &f);
609         glGetBooleanv(e, &b);
610 
611         bool status = true;
612         if (max_value)
613         {
614             if (static_cast<GLint64>(i) < value)
615                 status = false;
616             if (i64 < value)
617                 status = false;
618             if (static_cast<GLint64>(f) < value)
619                 status = false;
620 
621             if (!status)
622             {
623                 m_context.getTestContext().getLog()
624                     << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at least "
625                     << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
626             }
627         }
628         else
629         {
630             if (static_cast<GLint64>(i) > value)
631                 status = false;
632             if (i64 > value)
633                 status = false;
634             if (static_cast<GLint64>(f) > value)
635                 status = false;
636 
637             if (!status)
638             {
639                 m_context.getTestContext().getLog()
640                     << tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at most "
641                     << static_cast<GLint>(value) << tcu::TestLog::EndMessage;
642             }
643         }
644         return status;
645     }
646 
Run()647     virtual long Run()
648     {
649         if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
650             return ERROR;
651         if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 0, true))
652             return ERROR;
653         if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 4, true))
654             return ERROR;
655         if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 4, true))
656             return ERROR;
657         if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 134217728 /* 2^27 */, true))
658             return ERROR;
659         if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 4, true))
660             return ERROR;
661         if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4, true))
662             return ERROR;
663         if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
664             return ERROR;
665         return NO_ERROR;
666     }
667 };
668 //-----------------------------------------------------------------------------
669 // 1.3 BasicBinding
670 //-----------------------------------------------------------------------------
671 class BasicBinding : public ShaderStorageBufferObjectBase
672 {
673     GLuint m_buffer[4];
674 
Check(GLenum e,GLuint expected)675     bool Check(GLenum e, GLuint expected)
676     {
677         GLint i;
678         GLint64 i64;
679         GLfloat f;
680         GLboolean b;
681 
682         GLfloat expectedFloat = static_cast<GLfloat>(expected);
683 
684         glGetIntegerv(e, &i);
685         glGetInteger64v(e, &i64);
686         glGetFloatv(e, &f);
687         glGetBooleanv(e, &b);
688 
689         bool status = true;
690         if (static_cast<GLuint>(i) != expected)
691             status = false;
692         if (static_cast<GLuint>(i64) != expected)
693             status = false;
694         if (static_cast<GLuint>(f) != expectedFloat)
695             status = false;
696         if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
697             status = false;
698 
699         if (!status)
700         {
701             m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " is " << i
702                                                 << " should be " << expected << tcu::TestLog::EndMessage;
703         }
704         return status;
705     }
706 
CheckIndexed(GLenum e,GLuint index,GLuint expected)707     bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
708     {
709         GLint i;
710         GLint64 i64;
711 
712         glGetIntegeri_v(e, index, &i);
713         glGetInteger64i_v(e, index, &i64);
714 
715         bool status = true;
716         if (static_cast<GLuint>(i) != expected)
717             status = false;
718         if (static_cast<GLuint>(i64) != expected)
719             status = false;
720 
721         if (!status)
722         {
723             m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " at index " << index
724                                                 << " is " << i << " should be " << expected << tcu::TestLog::EndMessage;
725         }
726         return status;
727     }
728 
Setup()729     virtual long Setup()
730     {
731         memset(m_buffer, 0, sizeof(m_buffer));
732         return NO_ERROR;
733     }
734 
Run()735     virtual long Run()
736     {
737         GLint maxShaderStorageBufferBindings = 0;
738         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
739 
740         // check default state
741         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
742             return ERROR;
743         for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
744         {
745             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
746                 return ERROR;
747             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
748                 return ERROR;
749             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
750                 return ERROR;
751         }
752 
753         glGenBuffers(4, m_buffer);
754         for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
755         {
756             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
757 
758             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
759                 return ERROR;
760             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
761                 return ERROR;
762             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
763                 return ERROR;
764             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
765                 return ERROR;
766 
767             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
768 
769             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
770                 return ERROR;
771             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
772                 return ERROR;
773             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
774                 return ERROR;
775             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
776                 return ERROR;
777         }
778 
779         for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
780         {
781             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
782 
783             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
784                 return ERROR;
785             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
786                 return ERROR;
787             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
788                 return ERROR;
789             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
790                 return ERROR;
791 
792             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
793 
794             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
795                 return ERROR;
796             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
797                 return ERROR;
798             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
799                 return ERROR;
800             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
801                 return ERROR;
802 
803             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
804 
805             if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
806                 return ERROR;
807             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
808                 return ERROR;
809             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
810                 return ERROR;
811             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
812                 return ERROR;
813         }
814 
815         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
816         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
817             return ERROR;
818         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
819             return ERROR;
820         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
821             return ERROR;
822         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
823             return ERROR;
824 
825         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
826         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
827             return ERROR;
828         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
829             return ERROR;
830         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
831             return ERROR;
832         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
833             return ERROR;
834 
835         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
836         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
837             return ERROR;
838         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
839             return ERROR;
840         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
841             return ERROR;
842         if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
843             return ERROR;
844 
845         glDeleteBuffers(4, m_buffer);
846         memset(m_buffer, 0, sizeof(m_buffer));
847 
848         if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
849             return ERROR;
850         for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
851         {
852             if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
853                 return ERROR;
854         }
855 
856         return NO_ERROR;
857     }
858 
Cleanup()859     virtual long Cleanup()
860     {
861         glDeleteBuffers(4, m_buffer);
862         return NO_ERROR;
863     }
864 };
865 
866 //-----------------------------------------------------------------------------
867 // 1.4 BasicSyntax
868 //-----------------------------------------------------------------------------
869 class BasicSyntaxVS : public ShaderStorageBufferObjectBase
870 {
871     GLuint m_program;
872     GLuint m_buffer;
873     GLuint m_vertex_array;
874 
RunIteration(const char * vs,const char * fs)875     bool RunIteration(const char *vs, const char *fs)
876     {
877         if (m_program != 0)
878             glDeleteProgram(m_program);
879         m_program = CreateProgram(vs, fs);
880         glLinkProgram(m_program);
881         if (!CheckProgram(m_program))
882             return false;
883 
884         glClear(GL_COLOR_BUFFER_BIT);
885         glUseProgram(m_program);
886         glDrawArrays(GL_TRIANGLES, 0, 3);
887 
888         return CheckFB(vec3(0, 1, 0));
889     }
890 
Setup()891     virtual long Setup()
892     {
893         m_program      = 0;
894         m_buffer       = 0;
895         m_vertex_array = 0;
896         return NO_ERROR;
897     }
898 
Run()899     virtual long Run()
900     {
901         if (!IsVSFSAvailable(1, 0))
902             return NOT_SUPPORTED;
903         const int kCount                  = 8;
904         const char *const glsl_vs[kCount] = {
905             NL "layout(std430) buffer Buffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
906                "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
907             NL "coherent buffer Buffer {" NL "  buffer vec4 position0;" NL "  coherent vec4 position1;" NL
908                "  restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
909                "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
910                "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
911                "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
912             NL "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
913                "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
914             NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
915                "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
916                "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
917                "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
918             NL "buffer Buffer {" NL "  vec4 position[3];" //
919             NL "} g_buffer[1];" NL "void main() {" NL "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
920             NL "layout(shared) coherent buffer Buffer {" NL "  restrict volatile vec4 position0;" NL
921                "  buffer readonly vec4 position1;" NL "  vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
922                "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
923                "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
924                "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
925             NL "layout(packed) coherent buffer Buffer {" NL "  vec4 position01[2];" NL "  vec4 position2;" NL
926                "} g_buffer;" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
927                "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
928                "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
929             NL "layout(std430) coherent buffer Buffer {" NL "  coherent vec4 position01[2];" NL "  vec4 position2[];" NL
930                "} g_buffer;" NL "void main() {" NL "  switch (gl_VertexID) {" NL
931                "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
932                "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
933                "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
934         };
935         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
936                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
937 
938         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};
939         glGenBuffers(1, &m_buffer);
940         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
941         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
942 
943         glGenVertexArrays(1, &m_vertex_array);
944         glBindVertexArray(m_vertex_array);
945 
946         for (int i = 0; i < kCount; ++i)
947         {
948             if (!RunIteration(glsl_vs[i], glsl_fs))
949                 return ERROR;
950         }
951 
952         return NO_ERROR;
953     }
954 
Cleanup()955     virtual long Cleanup()
956     {
957         glUseProgram(0);
958         glDeleteProgram(m_program);
959         glDeleteBuffers(1, &m_buffer);
960         glDeleteVertexArrays(1, &m_vertex_array);
961         return NO_ERROR;
962     }
963 };
964 
965 class BasicSyntaxCS : public ShaderStorageBufferObjectBase
966 {
967     GLuint m_program;
968     GLuint m_buffer[2];
969 
RunIteration(const char * cs)970     bool RunIteration(const char *cs)
971     {
972         std::stringstream ss;
973         ss << "layout(local_size_x = 3) in;" NL "layout (std430) buffer Result {" NL "  int result[3];" NL "};" << cs;
974 
975         if (m_program != 0)
976             glDeleteProgram(m_program);
977         m_program = CreateProgramCS(ss.str());
978         glLinkProgram(m_program);
979         if (!CheckProgram(m_program))
980             return false;
981 
982         glUseProgram(m_program);
983         glDispatchCompute(1, 1, 1);
984         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
985 
986         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[0]);
987         GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 3, GL_MAP_READ_BIT);
988         if (!out_data)
989             return false;
990         bool result = out_data[0] == 7 && out_data[1] == 17 && out_data[2] == 23;
991         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
992         GLint data[3] = {0};
993         glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 3, data, GL_STATIC_READ);
994 
995         return result;
996     }
997 
Setup()998     virtual long Setup()
999     {
1000         m_program = 0;
1001         memset(m_buffer, 0, sizeof(m_buffer));
1002         return NO_ERROR;
1003     }
1004 
Run()1005     virtual long Run()
1006     {
1007         const int kCount                  = 8;
1008         const char *const glsl_cs[kCount] = {
1009             NL "layout(std430, binding = 1) buffer Buffer {" NL "  vec4 indata[3];" NL "} g_input_buffer;" NL
1010                "void main() {" NL
1011                "  result[gl_LocalInvocationIndex] = int(g_input_buffer.indata[gl_LocalInvocationID.x].z);" NL "}",
1012 
1013             NL "layout(binding = 1) coherent buffer Buffer {" NL "  buffer vec4 indata0;" NL
1014                "  coherent vec4 indata1;" NL "  restrict readonly vec4 indata2;" NL "} g_input_buffer;" NL
1015                "void main() {" NL
1016                "  if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata0.z);" NL
1017                "  if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata1.z);" NL
1018                "  if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_input_buffer.indata2.z);" NL
1019                "}",
1020 
1021             NL "layout(std140, binding = 1) readonly buffer Buffer {" NL "  readonly vec4 indata[];" NL "};" NL
1022                "void main() {" NL "  result[gl_LocalInvocationIndex] = int(indata[gl_LocalInvocationID.x].z);" NL "}",
1023 
1024             NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1025                "layout(std430) buffer;" NL "layout(binding = 1) coherent restrict volatile buffer Buffer {" NL
1026                "  restrict coherent vec4 indata[];" NL "} g_buffer;" NL "void main() {" NL
1027                "  result[gl_LocalInvocationIndex] = int(g_buffer.indata[gl_LocalInvocationID.x].z);" NL "}",
1028 
1029             NL "layout(binding = 1) buffer Buffer {" NL "  vec4 indata[3];" //
1030             NL "} g_buffer[1];" NL "void main() {" NL
1031                "  result[gl_LocalInvocationIndex] = int(g_buffer[0].indata[gl_LocalInvocationID.x].z);" NL "}",
1032 
1033             NL
1034             "layout(shared, binding = 1) coherent buffer Buffer {" NL "  restrict volatile vec4 indata0;" NL
1035             "  buffer readonly vec4 indata1;" NL "  vec4 indata2;" NL "} g_buffer[1];" NL "void main() {" NL
1036             "  if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata0.z);" NL
1037             "  else if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata1.z);" NL
1038             "  else if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_buffer[0].indata2.z);" NL
1039             "}",
1040 
1041             NL
1042             "layout(packed, binding = 1) coherent buffer Buffer {" NL "  vec4 indata01[2];" NL "  vec4 indata2;" NL
1043             "} g_buffer;" NL "void main() {" NL
1044             "  if (gl_LocalInvocationID.x == 0u) result[gl_LocalInvocationIndex] = int(g_buffer.indata01[0].z);" NL
1045             "  else if (gl_LocalInvocationID.x == 1u) result[gl_LocalInvocationIndex] = int(g_buffer.indata01[1].z);" NL
1046             "  else if (gl_LocalInvocationID.x == 2u) result[gl_LocalInvocationIndex] = int(g_buffer.indata2.z);" NL
1047             "}",
1048 
1049             NL "layout(std430, binding = 1) coherent buffer Buffer {" NL "  coherent vec4 indata01[2];" NL
1050                "  vec4 indata2[];" NL "} g_buffer;" NL "void main() {" NL "  switch (gl_LocalInvocationID.x) {" NL
1051                "    case 0u: result[gl_LocalInvocationIndex] = int(g_buffer.indata01[0].z); break;" NL
1052                "    case 1u: result[gl_LocalInvocationIndex] = int(g_buffer.indata01[1].z); break;" NL
1053                "    case 2u: result[gl_LocalInvocationIndex] = int(g_buffer.indata2[gl_LocalInvocationIndex-2u].z); "
1054                "break;" NL "  }" NL "}",
1055         };
1056 
1057         glGenBuffers(2, m_buffer);
1058         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1059         glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 3, 0, GL_STATIC_READ);
1060         const float data[12] = {-1.0f, -1.0f, 7.0f, 1.0f, 3.0f, -1.0f, 17.0f, 1.0f, -1.0f, 3.0f, 23.0f, 1.0f};
1061         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1062         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1063         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1064 
1065         for (int i = 0; i < kCount; ++i)
1066         {
1067             if (!RunIteration(glsl_cs[i]))
1068                 return ERROR;
1069         }
1070 
1071         return NO_ERROR;
1072     }
1073 
Cleanup()1074     virtual long Cleanup()
1075     {
1076         glUseProgram(0);
1077         glDeleteProgram(m_program);
1078         glDeleteBuffers(2, m_buffer);
1079         return NO_ERROR;
1080     }
1081 };
1082 //-----------------------------------------------------------------------------
1083 // 1.5 BasicSyntaxSSO
1084 //-----------------------------------------------------------------------------
1085 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1086 {
1087     GLuint m_pipeline;
1088     GLuint m_vsp, m_fsp;
1089     GLuint m_buffer;
1090     GLuint m_vertex_array;
1091 
RunIteration(const char * vs)1092     bool RunIteration(const char *vs)
1093     {
1094         if (m_vsp != 0)
1095             glDeleteProgram(m_vsp);
1096         m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1097         if (!CheckProgram(m_vsp))
1098             return false;
1099 
1100         glClear(GL_COLOR_BUFFER_BIT);
1101         glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1102         glDrawArrays(GL_TRIANGLES, 0, 3);
1103 
1104         return CheckFB(vec3(0, 1, 0));
1105     }
1106 
Setup()1107     virtual long Setup()
1108     {
1109         m_pipeline = 0;
1110         m_vsp = m_fsp  = 0;
1111         m_buffer       = 0;
1112         m_vertex_array = 0;
1113         return NO_ERROR;
1114     }
1115 
Run()1116     virtual long Run()
1117     {
1118         if (!IsVSFSAvailable(1, 0))
1119             return NOT_SUPPORTED;
1120         const int kCount = 8;
1121 
1122         const char *const glsl_vs[kCount] = {
1123             NL "layout(std430) buffer Buffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1124                "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1125             NL "coherent buffer Buffer {" NL "  vec4 position0;" NL "  coherent vec4 position1;" NL
1126                "  restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
1127                "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1128                "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1129                "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1130             NL "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
1131                "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
1132             NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1133                "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1134                "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1135                "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1136             NL "buffer Buffer {" NL "  vec4 position[3];" //
1137             NL "} g_buffer[1];" NL "void main() {" NL "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1138             NL "layout(shared) coherent buffer Buffer {" NL "  restrict volatile vec4 position0;" NL
1139                "  readonly vec4 position1;" NL "  vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
1140                "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1141                "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1142                "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1143             NL "layout(packed) coherent buffer Buffer {" NL "  vec4 position01[2];" NL "  vec4 position2;" NL
1144                "} g_buffer;" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1145                "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1146                "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1147             NL "layout(std430) coherent buffer Buffer {" NL "  coherent vec4 position01[2];" NL "  vec4 position2[];" NL
1148                "} g_buffer;" NL "void main() {" NL "  switch (gl_VertexID) {" NL
1149                "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
1150                "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
1151                "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
1152         };
1153         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1154                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1155         m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
1156         if (!CheckProgram(m_fsp))
1157             return ERROR;
1158 
1159         glGenProgramPipelines(1, &m_pipeline);
1160         glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
1161 
1162         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};
1163         glGenBuffers(1, &m_buffer);
1164         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1165         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1166 
1167         glBindProgramPipeline(m_pipeline);
1168 
1169         glGenVertexArrays(1, &m_vertex_array);
1170         glBindVertexArray(m_vertex_array);
1171 
1172         for (int i = 0; i < kCount; ++i)
1173         {
1174             if (!RunIteration(glsl_vs[i]))
1175                 return ERROR;
1176         }
1177 
1178         return NO_ERROR;
1179     }
1180 
Cleanup()1181     virtual long Cleanup()
1182     {
1183         glDeleteProgramPipelines(1, &m_pipeline);
1184         glDeleteProgram(m_vsp);
1185         glDeleteProgram(m_fsp);
1186         glDeleteBuffers(1, &m_buffer);
1187         glDeleteVertexArrays(1, &m_vertex_array);
1188         return NO_ERROR;
1189     }
1190 };
1191 
1192 //-----------------------------------------------------------------------------
1193 // 1.6.x BasicStdLayoutBase
1194 //-----------------------------------------------------------------------------
1195 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1196 {
1197     GLuint m_program;
1198     GLuint m_buffer[2];
1199     GLuint m_vertex_array;
1200 
1201     virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1202 
Setup()1203     virtual long Setup()
1204     {
1205         m_program = 0;
1206         memset(m_buffer, 0, sizeof(m_buffer));
1207         m_vertex_array = 0;
1208         return NO_ERROR;
1209     }
1210 
Run()1211     virtual long Run()
1212     {
1213         if (!IsVSFSAvailable(2, 0))
1214             return NOT_SUPPORTED;
1215         std::vector<GLubyte> in_data;
1216         const char *glsl_vs       = GetInput(in_data);
1217         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1218                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1219 
1220         m_program = CreateProgram(glsl_vs, glsl_fs);
1221         glLinkProgram(m_program);
1222         if (!CheckProgram(m_program))
1223             return ERROR;
1224 
1225         glGenBuffers(2, m_buffer);
1226 
1227         std::vector<GLubyte> out_d(in_data.size());
1228         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1229         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &out_d[0], GL_STATIC_DRAW);
1230 
1231         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1232         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1233 
1234         glGenVertexArrays(1, &m_vertex_array);
1235         glEnable(GL_RASTERIZER_DISCARD);
1236 
1237         glUseProgram(m_program);
1238         glBindVertexArray(m_vertex_array);
1239         glDrawArrays(GL_POINTS, 0, 1);
1240 
1241         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1242         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1243         GLubyte *out_data =
1244             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1245         if (!out_data)
1246             return ERROR;
1247 
1248         bool status = true;
1249         for (size_t i = 0; i < in_data.size(); ++i)
1250         {
1251             if (in_data[i] != out_data[i])
1252             {
1253                 m_context.getTestContext().getLog()
1254                     << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1255                     << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1256                 status = false;
1257             }
1258         }
1259         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1260         if (!status)
1261             return ERROR;
1262         return NO_ERROR;
1263     }
1264 
Cleanup()1265     virtual long Cleanup()
1266     {
1267         glDisable(GL_RASTERIZER_DISCARD);
1268         glUseProgram(0);
1269         glDeleteProgram(m_program);
1270         glDeleteBuffers(2, m_buffer);
1271         glDeleteVertexArrays(1, &m_vertex_array);
1272         return NO_ERROR;
1273     }
1274 };
1275 
1276 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1277 {
1278     GLuint m_program;
1279     GLuint m_buffer[2];
1280 
1281     virtual const char *GetInput(std::vector<GLubyte> &in_data) = 0;
1282 
Setup()1283     virtual long Setup()
1284     {
1285         m_program = 0;
1286         memset(m_buffer, 0, sizeof(m_buffer));
1287         return NO_ERROR;
1288     }
1289 
Run()1290     virtual long Run()
1291     {
1292         std::vector<GLubyte> in_data;
1293         std::stringstream ss;
1294         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1295 
1296         m_program = CreateProgramCS(ss.str());
1297         glLinkProgram(m_program);
1298         if (!CheckProgram(m_program))
1299             return ERROR;
1300 
1301         glGenBuffers(2, m_buffer);
1302 
1303         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1304         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1305         std::vector<GLubyte> out_d(in_data.size());
1306         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1307         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)out_d.size(), &out_d[0], GL_STATIC_DRAW);
1308 
1309         glUseProgram(m_program);
1310         glDispatchCompute(1, 1, 1);
1311 
1312         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1313         GLubyte *out_data =
1314             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1315         if (!out_data)
1316             return ERROR;
1317 
1318         bool status = true;
1319 
1320         for (size_t i = 0; i < in_data.size(); ++i)
1321         {
1322             if (in_data[i] != out_data[i])
1323             {
1324                 m_context.getTestContext().getLog()
1325                     << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1326                     << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1327                 status = false;
1328             }
1329             else
1330             {
1331             }
1332         }
1333         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1334         if (!status)
1335             return ERROR;
1336         return NO_ERROR;
1337     }
1338 
Cleanup()1339     virtual long Cleanup()
1340     {
1341         glUseProgram(0);
1342         glDeleteProgram(m_program);
1343         glDeleteBuffers(2, m_buffer);
1344         return NO_ERROR;
1345     }
1346 };
1347 
1348 //-----------------------------------------------------------------------------
1349 // 1.6.1 BasicStd430LayoutCase1
1350 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1351 const char *GetInput430c1(std::vector<GLubyte> &in_data)
1352 {
1353     in_data.resize(6 * 4);
1354     float *fp = reinterpret_cast<float *>(&in_data[0]);
1355     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1356     fp[0]     = 1.0f;
1357     fp[1]     = 2.0f;
1358     fp[2]     = 3.0f;
1359     fp[3]     = 4.0f;
1360     ip[4]     = 5;
1361     ip[5]     = 6;
1362     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1363               "  ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL
1364               "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1365               "  g_output.data0 = g_input.data0;" NL
1366               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1367               "  g_output.data2 = g_input.data2;" NL "}";
1368 }
1369 
1370 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1371 {
GetInput(std::vector<GLubyte> & in_data)1372     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1373     {
1374         return GetInput430c1(in_data);
1375     }
1376 };
1377 
1378 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1379 {
GetInput(std::vector<GLubyte> & in_data)1380     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1381     {
1382         return GetInput430c1(in_data);
1383     }
1384 };
1385 
1386 //-----------------------------------------------------------------------------
1387 // 1.6.2 BasicStd430LayoutCase2
1388 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1389 const char *GetInput430c2(std::vector<GLubyte> &in_data)
1390 {
1391     in_data.resize(17 * 4);
1392     float *fp = reinterpret_cast<float *>(&in_data[0]);
1393     fp[0]     = 1.0f;
1394     fp[1]     = 2.0f;
1395     fp[2]     = 3.0f;
1396     fp[3]     = 4.0f;
1397     fp[4]     = 5.0f;
1398     fp[5]     = 6.0f;
1399     fp[8]     = 7.0f;
1400     fp[9]     = 8.0f;
1401     fp[10]    = 9.0f;
1402     fp[12]    = 10.0f;
1403     fp[13]    = 11.0f;
1404     fp[14]    = 12.0f;
1405     fp[16]    = 13.0f;
1406     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1407               "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1408               "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1409               "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1410               "  g_output.data0 = g_input.data0;" NL
1411               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1412               "  g_output.data2 = g_input.data2;" NL
1413               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1414               "  g_output.data4 = g_input.data4;" NL "}";
1415 }
1416 
1417 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1418 {
GetInput(std::vector<GLubyte> & in_data)1419     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1420     {
1421         return GetInput430c2(in_data);
1422     }
1423 };
1424 
1425 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1426 {
GetInput(std::vector<GLubyte> & in_data)1427     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1428     {
1429         return GetInput430c2(in_data);
1430     }
1431 };
1432 
1433 //-----------------------------------------------------------------------------
1434 // 1.6.3 BasicStd430LayoutCase3
1435 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1436 const char *GetInput430c3(std::vector<GLubyte> &in_data)
1437 {
1438     in_data.resize(16 * 4);
1439     float *fp = reinterpret_cast<float *>(&in_data[0]);
1440     fp[0]     = 1.0f;
1441     fp[1]     = 2.0f;
1442     fp[2]     = 3.0f;
1443     fp[3]     = 0.0f;
1444     fp[4]     = 4.0f;
1445     fp[5]     = 5.0f;
1446     fp[6]     = 6.0f;
1447     fp[7]     = 0.0f;
1448     fp[8]     = 7.0f;
1449     fp[9]     = 8.0f;
1450     fp[10]    = 9.0f;
1451     fp[11]    = 10.0f;
1452     fp[12]    = 11.0f;
1453     fp[13]    = 12.0f;
1454     fp[14]    = 13.0f;
1455     fp[15]    = 14.0f;
1456     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat2x3 data0;" NL
1457               "  layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1458               "  layout(column_major) mat2x3 data0;" NL "  layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1459               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL "}";
1460 }
1461 
1462 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1463 {
GetInput(std::vector<GLubyte> & in_data)1464     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1465     {
1466         return GetInput430c3(in_data);
1467     }
1468 };
1469 
1470 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1471 {
GetInput(std::vector<GLubyte> & in_data)1472     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1473     {
1474         return GetInput430c3(in_data);
1475     }
1476 };
1477 
1478 //-----------------------------------------------------------------------------
1479 // 1.6.4 BasicStd430LayoutCase4
1480 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1481 const char *GetInput430c4(std::vector<GLubyte> &in_data)
1482 {
1483     in_data.resize(17 * 4);
1484     float *fp = reinterpret_cast<float *>(&in_data[0]);
1485     fp[0]     = 1.0f;
1486     fp[1]     = 2.0f;
1487     fp[2]     = 3.0f;
1488     fp[3]     = 4.0f;
1489     fp[4]     = 5.0f;
1490     fp[5]     = 6.0f;
1491     fp[6]     = 7.0f;
1492     fp[7]     = 8.0f;
1493     fp[8]     = 9.0f;
1494     fp[9]     = 10.0f;
1495     fp[10]    = 11.0f;
1496     fp[12]    = 12.0f;
1497     fp[13]    = 13.0f;
1498     fp[14]    = 14.0f;
1499     fp[16]    = 15.0f;
1500 
1501     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1502               "  float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1503               "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1504               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1505               "  g_output.data2 = g_input.data2;" NL "}";
1506 }
1507 
1508 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1509 {
GetInput(std::vector<GLubyte> & in_data)1510     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1511     {
1512         return GetInput430c4(in_data);
1513     }
1514 };
1515 
1516 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1517 {
GetInput(std::vector<GLubyte> & in_data)1518     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1519     {
1520         return GetInput430c4(in_data);
1521     }
1522 };
1523 //-----------------------------------------------------------------------------
1524 // 1.6.5 BasicStd430LayoutCase5
1525 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1526 const char *GetInput430c5(std::vector<GLubyte> &in_data)
1527 {
1528     in_data.resize(8 * 4);
1529     float *fp = reinterpret_cast<float *>(&in_data[0]);
1530     fp[0]     = 1.0f;
1531     fp[1]     = 3.0f;
1532     fp[2]     = 5.0f;
1533     fp[3]     = 7.0f;
1534     fp[4]     = 2.0f;
1535     fp[5]     = 4.0f;
1536     fp[6]     = 6.0f;
1537     fp[7]     = 8.0f;
1538 
1539     return NL "layout(std430, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1540               "layout(std430, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1541               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1542 }
1543 
1544 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1545 {
GetInput(std::vector<GLubyte> & in_data)1546     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1547     {
1548         return GetInput430c5(in_data);
1549     }
1550 };
1551 
1552 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1553 {
GetInput(std::vector<GLubyte> & in_data)1554     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1555     {
1556         return GetInput430c5(in_data);
1557     }
1558 };
1559 
1560 //-----------------------------------------------------------------------------
1561 // 1.6.6 BasicStd430LayoutCase6
1562 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1563 const char *GetInput430c6(std::vector<GLubyte> &in_data)
1564 {
1565     in_data.resize(92 * 4);
1566     float *fp = reinterpret_cast<float *>(&in_data[0]);
1567     fp[0]     = 1.0f;
1568     fp[1]     = 2.0f;
1569     fp[2]     = 3.0f;
1570     fp[3]     = 4.0f;
1571     fp[4]     = 5.0f;
1572     fp[5]     = 0.0f;
1573     fp[6]     = 6.0f;
1574     fp[7]     = 7.0f;
1575     fp[8]     = 8.0f;
1576     fp[9]     = 9.0f;
1577     fp[10]    = 10.0f;
1578     fp[11]    = 11.0f;
1579     fp[12]    = 12.0f;
1580     fp[13]    = 0.0f;
1581     fp[14]    = 0.0f;
1582     fp[15]    = 0.0f;
1583     fp[16]    = 13.0f;
1584     fp[17]    = 14.0f;
1585     fp[18]    = 15.0f;
1586     fp[19]    = 0.0f;
1587     fp[20]    = 16.0f;
1588     fp[21]    = 17.0f;
1589     fp[22]    = 18.0f;
1590     fp[23]    = 0.0f;
1591     fp[24]    = 19.0f;
1592     fp[25]    = 20.0f;
1593     fp[26]    = 21.0f;
1594     fp[27]    = 22.0f;
1595     fp[28]    = 23.0f;
1596     fp[29]    = 24.0f;
1597     fp[30]    = 25.0f;
1598     fp[31]    = 26.0f;
1599     fp[32]    = 27.0f;
1600     fp[33]    = 28.0f;
1601     fp[34]    = 0.0f;
1602     fp[35]    = 0.0f;
1603     fp[36]    = 29.0f;
1604     fp[37]    = 30.0f;
1605     fp[38]    = 31.0f;
1606     fp[39]    = 0.0f;
1607     fp[40]    = 32.0f;
1608     fp[41]    = 33.0f;
1609     fp[42]    = 34.0f;
1610     fp[43]    = 0.0f;
1611     fp[44]    = 35.0f;
1612     fp[45]    = 36.0f;
1613     fp[46]    = 37.0f;
1614     fp[47]    = 0.0f;
1615     fp[48]    = 38.0f;
1616     fp[49]    = 39.0f;
1617     fp[50]    = 40.0f;
1618     fp[51]    = 0.0f;
1619     fp[52]    = 41.0f;
1620     fp[53]    = 42.0f;
1621     fp[54]    = 43.0f;
1622     fp[55]    = 0.0f;
1623     fp[56]    = 44.0f;
1624     fp[57]    = 45.0f;
1625     fp[58]    = 46.0f;
1626     fp[59]    = 0.0f;
1627     fp[60]    = 47.0f;
1628     fp[61]    = 48.0f;
1629     fp[62]    = 49.0f;
1630     fp[63]    = 50.0f;
1631     fp[64]    = 51.0f;
1632     fp[65]    = 52.0f;
1633     fp[66]    = 53.0f;
1634     fp[67]    = 54.0f;
1635     fp[68]    = 55.0f;
1636     fp[69]    = 56.0f;
1637     fp[70]    = 57.0f;
1638     fp[71]    = 58.0f;
1639     fp[72]    = 59.0f;
1640     fp[73]    = 60.0f;
1641     fp[74]    = 61.0f;
1642     fp[75]    = 62.0f;
1643     fp[76]    = 63.0f;
1644     fp[77]    = 64.0f;
1645     fp[78]    = 65.0f;
1646     fp[79]    = 66.0f;
1647     fp[80]    = 67.0f;
1648     fp[81]    = 68.0f;
1649     fp[82]    = 69.0f;
1650     fp[83]    = 70.0f;
1651     fp[84]    = 71.0f;
1652     fp[85]    = 72.0f;
1653     fp[86]    = 73.0f;
1654     fp[87]    = 74.0f;
1655     fp[88]    = 75.0f;
1656     fp[89]    = 76.0f;
1657     fp[90]    = 77.0f;
1658     fp[91]    = 78.0f;
1659 
1660     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
1661               "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1662               "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_input;" NL
1663               "layout(std430, binding = 1) buffer Output {" NL "  float data0[2];" NL "  float data1[3];" NL
1664               "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1665               "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1666               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1667               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1668               "  g_output.data2 = g_input.data2;" NL
1669               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1670               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1671               "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1672               "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1673               "  for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1674               "  for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1675 }
1676 
1677 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1678 {
GetInput(std::vector<GLubyte> & in_data)1679     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1680     {
1681         return GetInput430c6(in_data);
1682     }
1683 };
1684 
1685 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1686 {
GetInput(std::vector<GLubyte> & in_data)1687     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1688     {
1689         return GetInput430c6(in_data);
1690     }
1691 };
1692 
1693 //-----------------------------------------------------------------------------
1694 // 1.6.7 BasicStd430LayoutCase7
1695 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1696 const char *GetInput430c7(std::vector<GLubyte> &in_data)
1697 {
1698     in_data.resize(36 * 4);
1699     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1700     float *fp = reinterpret_cast<float *>(&in_data[0]);
1701     ip[0]     = 1;
1702     ip[1]     = 0;
1703     ip[2]     = 2;
1704     ip[3]     = 3;
1705     fp[4]     = 4.0f;
1706     fp[5]     = 0.0f;
1707     fp[6]     = 0.0f;
1708     fp[7]     = 0.0f;
1709     fp[8]     = 5.0f;
1710     fp[9]     = 6.0f;
1711     fp[10]    = 7.0f;
1712     fp[11]    = 0.0f;
1713     fp[12]    = 8.0f;
1714     fp[13]    = 0.0f;
1715     fp[14]    = 0.0f;
1716     fp[15]    = 0.0f;
1717     fp[16]    = 9.0f;
1718     fp[17]    = 10.0f;
1719     fp[18]    = 11.0f;
1720     fp[19]    = 0.0f;
1721     ip[20]    = 12;
1722     ip[21]    = 13;
1723     ip[22]    = 14;
1724     ip[23]    = 15;
1725     fp[24]    = 16.0f;
1726     fp[25]    = 0.0f;
1727     fp[26]    = 0.0f;
1728     fp[27]    = 0.0f;
1729     fp[28]    = 17.0f;
1730     fp[29]    = 18.0f;
1731     fp[30]    = 19.0f;
1732     fp[31]    = 0.0f;
1733     ip[32]    = 20;
1734     ip[33]    = 21;
1735     ip[34]    = 22;
1736     ip[35]    = 23;
1737 
1738     return NL "struct Struct0 {" NL "  ivec2 m0;" NL "};" NL "struct Struct1 {" NL "  vec3 m0;" NL "};" NL
1739               "struct Struct3 {" NL "  int m0;" NL "};" NL "struct Struct2 {" NL "  float m0;" // offset = 0
1740         NL "  Struct1 m1;"                                                                     // offset = 16
1741         NL "  Struct0 m2;"                                                                     // offset = 32
1742         NL "  int m3;"                                                                         // offset = 40
1743         NL "  Struct3 m4;"                                                                     // offset = 44
1744         NL "};" NL "layout(std430, binding = 0) buffer Input {" NL "  int data0;"              // offset = 0
1745         NL "  Struct0 data1;"                                                                  // offset = 8
1746         NL "  float data2;"                                                                    // offset = 16
1747         NL "  Struct1 data3;"                                                                  // offset = 32
1748         NL "  Struct2 data4[2];"                                                               // offset = 48
1749         NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  int data0;" NL "  Struct0 data1;" NL
1750               "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1751               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1752               "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
1753               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1754 }
1755 
1756 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1757 {
GetInput(std::vector<GLubyte> & in_data)1758     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1759     {
1760         return GetInput430c7(in_data);
1761     }
1762 };
1763 
1764 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1765 {
GetInput(std::vector<GLubyte> & in_data)1766     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1767     {
1768         return GetInput430c7(in_data);
1769     }
1770 };
1771 
1772 //-----------------------------------------------------------------------------
1773 // 1.7.1 BasicStd140LayoutCase1
1774 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1775 const char *GetInput140c1(std::vector<GLubyte> &in_data)
1776 {
1777     in_data.resize(5 * 4);
1778     float *fp = reinterpret_cast<float *>(&in_data[0]);
1779     fp[0]     = 1.0f;
1780     fp[1]     = 0.0f;
1781     fp[2]     = 0.0f;
1782     fp[3]     = 0.0f;
1783     fp[4]     = 2.0f;
1784 
1785     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "} g_input;" NL
1786               "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL "} g_output;" NL
1787               "void main() {" NL
1788               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1789 }
1790 
1791 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1792 {
GetInput(std::vector<GLubyte> & in_data)1793     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1794     {
1795         return GetInput140c1(in_data);
1796     }
1797 };
1798 
1799 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1800 {
GetInput(std::vector<GLubyte> & in_data)1801     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1802     {
1803         return GetInput140c1(in_data);
1804     }
1805 };
1806 
1807 //-----------------------------------------------------------------------------
1808 // 1.7.2 BasicStd140LayoutCase2
1809 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1810 const char *GetInput140c2(std::vector<GLubyte> &in_data)
1811 {
1812     in_data.resize(18 * 4);
1813     float *fp = reinterpret_cast<float *>(&in_data[0]);
1814     int *ip   = reinterpret_cast<int *>(&in_data[0]);
1815     fp[0]     = 1.0f;
1816     fp[1]     = 0.0f;
1817     fp[2]     = 0.0f;
1818     fp[3]     = 0.0f;
1819     fp[4]     = 2.0f;
1820     fp[5]     = 0.0f;
1821     fp[6]     = 0.0f;
1822     fp[7]     = 0.0f;
1823     fp[8]     = 3.0f;
1824     fp[9]     = 0.0f;
1825     fp[10]    = 0.0f;
1826     fp[11]    = 0.0f;
1827     fp[12]    = 4.0f;
1828     fp[13]    = 0.0f;
1829     fp[14]    = 0.0f;
1830     fp[15]    = 0.0f;
1831     ip[16]    = 5;
1832     ip[17]    = 6;
1833 
1834     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1835               "  ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL
1836               "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1837               "  g_output.data0 = g_input.data0;" NL
1838               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1839               "  g_output.data2 = g_input.data2;" NL "}";
1840 }
1841 
1842 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1843 {
GetInput(std::vector<GLubyte> & in_data)1844     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1845     {
1846         return GetInput140c2(in_data);
1847     }
1848 };
1849 
1850 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1851 {
GetInput(std::vector<GLubyte> & in_data)1852     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1853     {
1854         return GetInput140c2(in_data);
1855     }
1856 };
1857 
1858 //-----------------------------------------------------------------------------
1859 // 1.7.3 BasicStd140LayoutCase3
1860 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1861 const char *GetInput140c3(std::vector<GLubyte> &in_data)
1862 {
1863     in_data.resize(29 * 4);
1864     float *fp = reinterpret_cast<float *>(&in_data[0]);
1865     fp[0]     = 1.0f;
1866     fp[1]     = 0.0f;
1867     fp[2]     = 0.0f;
1868     fp[3]     = 0.0f;
1869     fp[4]     = 2.0f;
1870     fp[5]     = 0.0f;
1871     fp[6]     = 0.0f;
1872     fp[7]     = 0.0f;
1873     fp[8]     = 3.0f;
1874     fp[9]     = 0.0f;
1875     fp[10]    = 0.0f;
1876     fp[11]    = 0.0f;
1877     fp[12]    = 4.0f;
1878     fp[13]    = 0.0f;
1879     fp[14]    = 0.0f;
1880     fp[15]    = 0.0f;
1881     fp[16]    = 5.0f;
1882     fp[17]    = 6.0f;
1883     fp[18]    = 0.0f;
1884     fp[19]    = 0.0f;
1885     fp[20]    = 7.0f;
1886     fp[21]    = 8.0f;
1887     fp[22]    = 9.0f;
1888     fp[23]    = 0.0f;
1889     fp[24]    = 10.0f;
1890     fp[25]    = 11.0f;
1891     fp[26]    = 12.0f;
1892     fp[27]    = 0.0f;
1893     fp[28]    = 13.0f;
1894     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1895               "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1896               "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1897               "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1898               "  g_output.data0 = g_input.data0;" NL
1899               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1900               "  g_output.data2 = g_input.data2;" NL
1901               "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1902               "  g_output.data4 = g_input.data4;" NL "}";
1903 }
1904 
1905 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1906 {
GetInput(std::vector<GLubyte> & in_data)1907     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1908     {
1909         return GetInput140c3(in_data);
1910     }
1911 };
1912 
1913 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1914 {
GetInput(std::vector<GLubyte> & in_data)1915     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1916     {
1917         return GetInput140c3(in_data);
1918     }
1919 };
1920 
1921 //-----------------------------------------------------------------------------
1922 // 1.7.4 BasicStd140LayoutCase4
1923 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1924 const char *GetInput140c4(std::vector<GLubyte> &in_data)
1925 {
1926     in_data.resize(25 * 4);
1927     float *fp = reinterpret_cast<float *>(&in_data[0]);
1928     fp[0]     = 1.0f;
1929     fp[1]     = 2.0f;
1930     fp[2]     = 0.0f;
1931     fp[3]     = 0.0f;
1932     fp[4]     = 3.0f;
1933     fp[5]     = 4.0f;
1934     fp[6]     = 0.0f;
1935     fp[7]     = 0.0f;
1936     fp[8]     = 5.0f;
1937     fp[9]     = 6.0f;
1938     fp[10]    = 0.0f;
1939     fp[11]    = 0.0f;
1940     fp[12]    = 7.0f;
1941     fp[13]    = 8.0f;
1942     fp[14]    = 0.0f;
1943     fp[15]    = 0.0f;
1944     fp[16]    = 9.0f;
1945     fp[17]    = 10.0f;
1946     fp[18]    = 11.0f;
1947     fp[19]    = 0.0f;
1948     fp[20]    = 12.0f;
1949     fp[21]    = 13.0f;
1950     fp[22]    = 14.0f;
1951     fp[23]    = 0.0f;
1952     fp[24]    = 15.0f;
1953 
1954     return NL "layout(std140, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1955               "  float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1956               "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1957               "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1958               "  g_output.data2 = g_input.data2;" NL "}";
1959 }
1960 
1961 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
1962 {
GetInput(std::vector<GLubyte> & in_data)1963     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1964     {
1965         return GetInput140c4(in_data);
1966     }
1967 };
1968 
1969 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
1970 {
GetInput(std::vector<GLubyte> & in_data)1971     virtual const char *GetInput(std::vector<GLubyte> &in_data)
1972     {
1973         return GetInput140c4(in_data);
1974     }
1975 };
1976 
1977 //-----------------------------------------------------------------------------
1978 // 1.7.5 BasicStd140LayoutCase5
1979 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)1980 const char *GetInput140c5(std::vector<GLubyte> &in_data)
1981 {
1982     in_data.resize(8 * 4);
1983     float *fp = reinterpret_cast<float *>(&in_data[0]);
1984     fp[0]     = 1.0f;
1985     fp[1]     = 2.0f;
1986     fp[2]     = 3.0f;
1987     fp[3]     = 4.0f;
1988     fp[4]     = 5.0f;
1989     fp[5]     = 6.0f;
1990     fp[6]     = 7.0f;
1991     fp[7]     = 8.0f;
1992     return NL "layout(std140, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1993               "layout(std140, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1994               "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1995 }
1996 
1997 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
1998 {
GetInput(std::vector<GLubyte> & in_data)1999     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2000     {
2001         return GetInput140c5(in_data);
2002     }
2003 };
2004 
2005 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2006 {
GetInput(std::vector<GLubyte> & in_data)2007     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2008     {
2009         return GetInput140c5(in_data);
2010     }
2011 };
2012 
2013 //-----------------------------------------------------------------------------
2014 // 1.7.6 BasicStd140LayoutCase6
2015 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2016 const char *GetInput140c6(std::vector<GLubyte> &in_data)
2017 {
2018     in_data.resize(96 * 4);
2019     float *fp = reinterpret_cast<float *>(&in_data[0]);
2020     fp[0]     = 1.0f;
2021     fp[1]     = 0.0f;
2022     fp[2]     = 0.0f;
2023     fp[3]     = 0.0f;
2024     fp[4]     = 2.0f;
2025     fp[5]     = 0.0f;
2026     fp[6]     = 0.0f;
2027     fp[7]     = 0.0f;
2028     fp[8]     = 3.0f;
2029     fp[9]     = 0.0f;
2030     fp[10]    = 0.0f;
2031     fp[11]    = 0.0f;
2032     fp[12]    = 4.0f;
2033     fp[13]    = 0.0f;
2034     fp[14]    = 0.0f;
2035     fp[15]    = 0.0f;
2036     fp[16]    = 5.0f;
2037     fp[17]    = 0.0f;
2038     fp[18]    = 0.0f;
2039     fp[19]    = 0.0f;
2040     fp[20]    = 6.0f;
2041     fp[21]    = 7.0f;
2042     fp[22]    = 8.0f;
2043     fp[23]    = 9.0f;
2044     fp[24]    = 10.0f;
2045     fp[25]    = 11.0f;
2046     fp[26]    = 0.0f;
2047     fp[27]    = 0.0f;
2048     fp[28]    = 12.0f;
2049     fp[29]    = 13.0f;
2050     fp[30]    = 0.0f;
2051     fp[31]    = 0.0f;
2052     fp[32]    = 14.0f;
2053     fp[33]    = 15.0f;
2054     fp[34]    = 0.0f;
2055     fp[35]    = 0.0f;
2056     fp[36]    = 16.0f;
2057     fp[37]    = 17.0f;
2058     fp[38]    = 0.0f;
2059     fp[39]    = 0.0f;
2060     fp[40]    = 18.0f;
2061     fp[41]    = 19.0f;
2062     fp[42]    = 20.0f;
2063     fp[43]    = 0.0f;
2064     fp[44]    = 21.0f;
2065     fp[45]    = 22.0f;
2066     fp[46]    = 23.0f;
2067     fp[47]    = 0.0f;
2068     fp[48]    = 24.0f;
2069     fp[49]    = 25.0f;
2070     fp[50]    = 26.0f;
2071     fp[51]    = 0.0f;
2072     fp[52]    = 27.0f;
2073     fp[53]    = 28.0f;
2074     fp[54]    = 29.0f;
2075     fp[55]    = 0.0f;
2076     fp[56]    = 30.0f;
2077     fp[57]    = 31.0f;
2078     fp[58]    = 32.0f;
2079     fp[59]    = 0.0f;
2080     fp[60]    = 33.0f;
2081     fp[61]    = 34.0f;
2082     fp[62]    = 35.0f;
2083     fp[63]    = 0.0f;
2084     fp[64]    = 36.0f;
2085     fp[65]    = 37.0f;
2086     fp[66]    = 38.0f;
2087     fp[67]    = 39.0f;
2088     fp[68]    = 40.0f;
2089     fp[69]    = 41.0f;
2090     fp[70]    = 42.0f;
2091     fp[71]    = 43.0f;
2092     fp[72]    = 44.0f;
2093     fp[73]    = 45.0f;
2094     fp[74]    = 46.0f;
2095     fp[75]    = 47.0f;
2096     fp[76]    = 48.0f;
2097     fp[77]    = 49.0f;
2098     fp[78]    = 50.0f;
2099     fp[79]    = 51.0f;
2100     fp[80]    = 52.0f;
2101     fp[81]    = 68.0f;
2102     fp[82]    = 69.0f;
2103     fp[83]    = 70.0f;
2104     fp[84]    = 56.0f;
2105     fp[85]    = 72.0f;
2106     fp[86]    = 73.0f;
2107     fp[87]    = 74.0f;
2108     fp[88]    = 60.0f;
2109     fp[89]    = 76.0f;
2110     fp[90]    = 77.0f;
2111     fp[91]    = 78.0f;
2112     fp[92]    = 64.0f;
2113     fp[93]    = 80.0f;
2114     fp[94]    = 81.0f;
2115     fp[95]    = 82.0f;
2116 
2117     return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
2118               "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL "  mat4 data6[2];" NL
2119               "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL
2120               "  float data1[3];" NL "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL
2121               "  mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2122               "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2123               "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2124               "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
2125               "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2126               "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2127               "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2128 }
2129 
2130 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2131 {
GetInput(std::vector<GLubyte> & in_data)2132     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2133     {
2134         return GetInput140c6(in_data);
2135     }
2136 };
2137 
2138 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2139 {
GetInput(std::vector<GLubyte> & in_data)2140     virtual const char *GetInput(std::vector<GLubyte> &in_data)
2141     {
2142         return GetInput140c6(in_data);
2143     }
2144 };
2145 
2146 //-----------------------------------------------------------------------------
2147 // 1.8.1 BasicAtomicCase1
2148 //-----------------------------------------------------------------------------
2149 class BasicAtomicCase1VSFS : public ShaderStorageBufferObjectBase
2150 {
2151     GLuint m_program;
2152     GLuint m_storage_buffer[4];
2153     GLuint m_vertex_array;
2154     GLuint m_vertex_buffer;
2155 
Setup()2156     virtual long Setup()
2157     {
2158         m_program = 0;
2159         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2160         m_vertex_array  = 0;
2161         m_vertex_buffer = 0;
2162         return NO_ERROR;
2163     }
2164 
Run()2165     virtual long Run()
2166     {
2167         if (!IsVSFSAvailable(2, 2))
2168             return NOT_SUPPORTED;
2169 
2170         const char *const glsl_vs = NL
2171             "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) coherent buffer VSuint {" NL
2172             "  uint g_uint_out[4];" NL "};" NL "layout(std430, binding = 1) coherent buffer VSint {" NL
2173             "  int data[4];" NL "} g_int_out;" NL "uniform uint g_uint_value[8];" NL "flat out int vertexid;" NL
2174             "void main() {" NL "  gl_Position = g_in_position;" NL "  vertexid = gl_VertexID;" NL "#ifdef GL_ES" NL
2175             "  gl_PointSize = 1.0f;" NL "#endif" NL NL
2176             "  // 0 is the initial value of g_uint_out while 7 is the value at the end shader execution." NL
2177             "  // Since vertex shader can be executed multiple times due to implementation dependent reasons," NL
2178             "  // initial validation should consider both value as possibility." NL
2179             "  uint ret = atomicExchange(g_uint_out[gl_VertexID], g_uint_value[1]);" NL
2180             "  if ((ret != 0u) && (ret != 7u)) return;" NL
2181             "  if (atomicAdd(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2182             "  if (atomicMin(g_uint_out[gl_VertexID], g_uint_value[1]) != 3u) return;" NL
2183             "  if (atomicMax(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2184             "  if (atomicAnd(g_uint_out[gl_VertexID], g_uint_value[3]) != 2u) return;" NL
2185             "  if (atomicOr(g_uint_out[gl_VertexID], g_uint_value[4]) != 0u) return;" NL
2186             "  if (g_uint_value[0] > 0u) {" NL
2187             "    if (atomicXor(g_uint_out[gl_VertexID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2188             "  if (atomicCompSwap(g_uint_out[gl_VertexID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2189             "    g_uint_out[gl_VertexID] = 1u;" NL "    return;" NL "  }" NL NL
2190             "  int ret2 = atomicExchange(g_int_out.data[gl_VertexID], 1);" NL
2191             "  if ((ret2 != 0) && (ret2 != 7)) return;" NL
2192             "  if (atomicAdd(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2193             "  if (atomicMin(g_int_out.data[gl_VertexID], 1) != 3) return;" NL
2194             "  if (atomicMax(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2195             "  if (atomicAnd(g_int_out.data[gl_VertexID], 0x1) != 2) return;" NL
2196             "  if (atomicOr(g_int_out.data[gl_VertexID], 0x3) != 0) return;" NL
2197             "  if (atomicXor(g_int_out.data[gl_VertexID], 0x1) != 3) return;" NL
2198             "  if (atomicCompSwap(g_int_out.data[gl_VertexID], 0x2, 0x7) != 2) {" NL
2199             "    g_int_out.data[gl_VertexID] = 1;" NL "    return;" NL "  }" NL "}";
2200 
2201         const char *const glsl_fs = NL
2202             "flat in int vertexid;" NL "layout(location = 0) out vec4 g_fs_out;" NL
2203             "layout(std430, binding = 2) coherent buffer FSuint {" NL "  uint data[4];" NL "} g_uint_fs;" NL
2204             "layout(std430, binding = 3) coherent buffer FSint {" NL "  int data[4];" NL "} g_int_fs;" NL
2205             "uniform uint g_uint_value[8];" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL NL
2206             "  if (atomicExchange(g_uint_fs.data[vertexid], g_uint_value[1]) != 0u) return;" // 0, 1
2207             NL "  if (atomicAdd(g_uint_fs.data[vertexid], g_uint_value[2]) != 1u) return;"   // 1, 2
2208             NL "  if (atomicMin(g_uint_fs.data[vertexid], g_uint_value[1]) != 3u) return;"   // 3, 1
2209             NL "  if (atomicMax(g_uint_fs.data[vertexid], g_uint_value[2]) != 1u) return;"   // 1, 2
2210             NL "  if (atomicAnd(g_uint_fs.data[vertexid], g_uint_value[3]) != 2u) return;"   // 2, 0x1
2211             NL "  if (atomicOr(g_uint_fs.data[vertexid], g_uint_value[4]) != 0u) return;"    // 0, 0x3
2212             NL "  if (g_uint_value[0] > 0u) {" NL
2213             "    if (atomicXor(g_uint_fs.data[vertexid], g_uint_value[5]) != 3u) return;" // 0x3, 0x1
2214             NL "  }" NL
2215             "  if (atomicCompSwap(g_uint_fs.data[vertexid], g_uint_value[6], g_uint_value[7]) != 2u) {" // 2, 0x2, 0x7
2216             NL "    g_uint_fs.data[vertexid] = 1u;" NL "    return;" NL "  }" NL NL
2217             "  if (atomicExchange(g_int_fs.data[vertexid], 1) != 0) return;" NL
2218             "  if (atomicAdd(g_int_fs.data[vertexid], 2) != 1) return;" NL
2219             "  if (atomicMin(g_int_fs.data[vertexid], 1) != 3) return;" NL
2220             "  if (atomicMax(g_int_fs.data[vertexid], 2) != 1) return;" NL
2221             "  if (atomicAnd(g_int_fs.data[vertexid], 0x1) != 2) return;" NL
2222             "  if (atomicOr(g_int_fs.data[vertexid], 0x3) != 0) return;" NL
2223             "  if (atomicXor(g_int_fs.data[vertexid], 0x1) != 3) return;" NL
2224             "  if (atomicCompSwap(g_int_fs.data[vertexid], 0x2, 0x7) != 2) {" NL "    g_int_fs.data[vertexid] = 1;" NL
2225             "    return;" NL "  }" NL "}";
2226         m_program = CreateProgram(glsl_vs, glsl_fs);
2227         glLinkProgram(m_program);
2228         if (!CheckProgram(m_program))
2229             return ERROR;
2230 
2231         glGenBuffers(4, m_storage_buffer);
2232         for (GLuint i = 0; i < 4; ++i)
2233         {
2234             const int data[4] = {0};
2235             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2236             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2237         }
2238 
2239         /* vertex buffer */
2240         {
2241             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2242             glGenBuffers(1, &m_vertex_buffer);
2243             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2244             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2245             glBindBuffer(GL_ARRAY_BUFFER, 0);
2246         }
2247 
2248         glGenVertexArrays(1, &m_vertex_array);
2249         glBindVertexArray(m_vertex_array);
2250         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2251         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2252         glBindBuffer(GL_ARRAY_BUFFER, 0);
2253         glEnableVertexAttribArray(0);
2254         glBindVertexArray(0);
2255 
2256         glClear(GL_COLOR_BUFFER_BIT);
2257         glUseProgram(m_program);
2258         GLuint unif[8] = {3, 1, 2, 1, 3, 1, 2, 7};
2259         glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2260 
2261         glBindVertexArray(m_vertex_array);
2262         glDrawArrays(GL_POINTS, 0, 4);
2263         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2264 
2265         for (int ii = 0; ii < 2; ++ii)
2266         {
2267             /* uint data */
2268             {
2269                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2270                 GLuint *data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2271                 if (!data)
2272                     return ERROR;
2273                 for (GLuint i = 0; i < 4; ++i)
2274                 {
2275                     if (data[i] != 7)
2276                     {
2277                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2278                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2279                         return ERROR;
2280                     }
2281                 }
2282                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2283             }
2284             /* int data */
2285             {
2286                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2287                 GLint *data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2288                 if (!data)
2289                     return ERROR;
2290                 for (GLint i = 0; i < 4; ++i)
2291                 {
2292                     if (data[i] != 7)
2293                     {
2294                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2295                                                             << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2296                         return ERROR;
2297                     }
2298                 }
2299                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2300             }
2301         }
2302         return NO_ERROR;
2303     }
2304 
Cleanup()2305     virtual long Cleanup()
2306     {
2307         glUseProgram(0);
2308         glDeleteProgram(m_program);
2309         glDeleteBuffers(4, m_storage_buffer);
2310         glDeleteBuffers(1, &m_vertex_buffer);
2311         glDeleteVertexArrays(1, &m_vertex_array);
2312         return NO_ERROR;
2313     }
2314 };
2315 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2316 {
2317     GLuint m_program;
2318     GLuint m_storage_buffer[2];
2319 
Setup()2320     virtual long Setup()
2321     {
2322         m_program = 0;
2323         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2324         return NO_ERROR;
2325     }
2326 
Run()2327     virtual long Run()
2328     {
2329         const char *const glsl_cs =
2330             NL "layout(local_size_x = 4) in;" NL "layout(std430, binding = 2) coherent buffer FSuint {" NL
2331                "  uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 3) coherent buffer FSint {" NL
2332                "  int data[4];" NL "} g_int_fs;" NL "uniform uint g_uint_value[8];" NL "void main() {" NL
2333                "  if (atomicExchange(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 0u) return;" // 0, 1
2334             NL "  if (atomicAdd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;"      // 1, 2
2335             NL "  if (atomicMin(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 3u) return;"      // 3, 1
2336             NL "  if (atomicMax(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;"      // 1, 2
2337             NL "  if (atomicAnd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[3]) != 2u) return;"      // 2, 0x1
2338             NL "  if (atomicOr(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[4]) != 0u) return;"       // 0, 0x3
2339             NL "  if (g_uint_value[0] > 0u) {" NL
2340                "    if (atomicXor(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[5]) != 3u) return;" // 0x3, 0x1
2341             NL "  }" NL "  if (atomicCompSwap(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[6], "
2342                "g_uint_value[7]) != 2u) {" // 2, 0x2, 0x7
2343             NL "    g_uint_fs.data[gl_LocalInvocationIndex] = 1u;" NL "    return;" NL "  }" NL
2344                "  if (atomicExchange(g_int_fs.data[gl_LocalInvocationIndex], 1) != 0) return;" NL
2345                "  if (atomicAdd(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2346                "  if (atomicMin(g_int_fs.data[gl_LocalInvocationIndex], 1) != 3) return;" NL
2347                "  if (atomicMax(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2348                "  if (atomicAnd(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 2) return;" NL
2349                "  if (atomicOr(g_int_fs.data[gl_LocalInvocationIndex], 0x3) != 0) return;" NL
2350                "  if (atomicXor(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 3) return;" NL
2351                "  if (atomicCompSwap(g_int_fs.data[gl_LocalInvocationIndex], 0x2, 0x7) != 2) {" NL
2352                "    g_int_fs.data[gl_LocalInvocationIndex] = 1;" NL "    return;" NL "  }" NL "}";
2353         m_program = CreateProgramCS(glsl_cs);
2354         glLinkProgram(m_program);
2355         if (!CheckProgram(m_program))
2356             return ERROR;
2357 
2358         glGenBuffers(2, m_storage_buffer);
2359         for (GLuint i = 0; i < 2; ++i)
2360         {
2361             const int data[4] = {0};
2362             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 2, m_storage_buffer[i]);
2363             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2364         }
2365 
2366         glUseProgram(m_program);
2367         GLuint unif[8] = {3, 1, 2, 1, 3, 1, 2, 7};
2368         glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2369         glDispatchCompute(1, 1, 1);
2370         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2371 
2372         /* uint data */
2373         {
2374             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
2375             GLuint *data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2376             if (!data)
2377                 return ERROR;
2378             for (GLuint i = 0; i < 4; ++i)
2379             {
2380                 if (data[i] != 7)
2381                 {
2382                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2383                                                         << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2384                     return ERROR;
2385                 }
2386             }
2387             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2388         }
2389         /* int data */
2390         {
2391             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
2392             GLint *data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2393             if (!data)
2394                 return ERROR;
2395             for (GLint i = 0; i < 4; ++i)
2396             {
2397                 if (data[i] != 7)
2398                 {
2399                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2400                                                         << data[i] << " should be 7." << tcu::TestLog::EndMessage;
2401                     return ERROR;
2402                 }
2403             }
2404             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2405         }
2406         return NO_ERROR;
2407     }
2408 
Cleanup()2409     virtual long Cleanup()
2410     {
2411         glUseProgram(0);
2412         glDeleteProgram(m_program);
2413         glDeleteBuffers(2, m_storage_buffer);
2414         return NO_ERROR;
2415     }
2416 };
2417 //-----------------------------------------------------------------------------
2418 // 1.8.3 BasicAtomicCase3
2419 //-----------------------------------------------------------------------------
2420 class BasicAtomicCase3VSFS : public ShaderStorageBufferObjectBase
2421 {
2422     GLuint m_program;
2423     GLuint m_storage_buffer;
2424     GLuint m_vertex_array;
2425     GLuint m_vertex_buffer;
2426 
Setup()2427     virtual long Setup()
2428     {
2429         m_program        = 0;
2430         m_storage_buffer = 0;
2431         m_vertex_array   = 0;
2432         m_vertex_buffer  = 0;
2433         return NO_ERROR;
2434     }
2435 
Run()2436     virtual long Run()
2437     {
2438         if (!IsVSFSAvailable(1, 1))
2439             return NOT_SUPPORTED;
2440         const char *const glsl_vs = NL
2441             "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) coherent buffer Buffer {" NL
2442             "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_vs_buffer;" NL "flat out int vertexid;" NL "void main() {" NL
2443             "  vertexid = gl_VertexID;" NL "  gl_Position = g_in_position;" NL "#ifdef GL_ES" NL
2444             "  gl_PointSize = 1.0f;" NL "#endif" NL "  atomicAdd(g_vs_buffer.u[0].x, g_vs_buffer.u[gl_VertexID][1]);" NL
2445             "  atomicAdd(g_vs_buffer.u[0][0], g_vs_buffer.u[gl_VertexID].z);" NL
2446             "  atomicAdd(g_vs_buffer.i[0].x, g_vs_buffer.i[gl_VertexID][1]);" NL
2447             "  atomicAdd(g_vs_buffer.i[0][0], g_vs_buffer.i[gl_VertexID].z);" NL "}";
2448         const char *const glsl_fs =
2449             NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) coherent buffer Buffer {" NL
2450                "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_fs_buffer;" NL "flat in int vertexid;" NL "void main() {" NL
2451                "  g_fs_out = vec4(0, 1, 0, 1);" NL "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[vertexid][1]);" NL
2452                "  atomicAdd(g_fs_buffer.i[0].x, g_fs_buffer.i[vertexid][1]);" NL "}";
2453         m_program = CreateProgram(glsl_vs, glsl_fs);
2454         glLinkProgram(m_program);
2455         if (!CheckProgram(m_program))
2456             return ERROR;
2457 
2458         /* init storage buffer */
2459         {
2460             glGenBuffers(1, &m_storage_buffer);
2461             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2462             glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2463             ivec4 *ptr = reinterpret_cast<ivec4 *>(
2464                 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2465             if (!ptr)
2466                 return ERROR;
2467             for (int i = 0; i < 4; ++i)
2468             {
2469                 ptr[i * 2]     = ivec4(0, 1, 2, 0);
2470                 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2471             }
2472             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2473         }
2474 
2475         /* init vertex buffer */
2476         {
2477             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2478             glGenBuffers(1, &m_vertex_buffer);
2479             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2480             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2481             glBindBuffer(GL_ARRAY_BUFFER, 0);
2482         }
2483 
2484         glGenVertexArrays(1, &m_vertex_array);
2485         glBindVertexArray(m_vertex_array);
2486         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2487         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2488         glBindBuffer(GL_ARRAY_BUFFER, 0);
2489         glEnableVertexAttribArray(0);
2490         glBindVertexArray(0);
2491 
2492         glClear(GL_COLOR_BUFFER_BIT);
2493         glUseProgram(m_program);
2494         glBindVertexArray(m_vertex_array);
2495         glDrawArrays(GL_POINTS, 0, 4);
2496         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2497 
2498         GLuint *u = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2499         if (!u)
2500             return ERROR;
2501         if (*u != 16)
2502         {
2503             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2504                                                 << " should be 16." << tcu::TestLog::EndMessage;
2505             return ERROR;
2506         }
2507         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2508         GLint *i = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2509         if (!i)
2510             return ERROR;
2511         if (*i != 16)
2512         {
2513             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2514                                                 << " should be 16." << tcu::TestLog::EndMessage;
2515             return ERROR;
2516         }
2517         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2518 
2519         return NO_ERROR;
2520     }
2521 
Cleanup()2522     virtual long Cleanup()
2523     {
2524         glUseProgram(0);
2525         glDeleteProgram(m_program);
2526         glDeleteBuffers(1, &m_storage_buffer);
2527         glDeleteBuffers(1, &m_vertex_buffer);
2528         glDeleteVertexArrays(1, &m_vertex_array);
2529         return NO_ERROR;
2530     }
2531 };
2532 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2533 {
2534     GLuint m_program;
2535     GLuint m_storage_buffer;
2536 
Setup()2537     virtual long Setup()
2538     {
2539         m_program        = 0;
2540         m_storage_buffer = 0;
2541         return NO_ERROR;
2542     }
2543 
Run()2544     virtual long Run()
2545     {
2546         const char *const glsl_cs =
2547             NL "layout(local_size_y = 4) in;" NL "layout(std430) coherent buffer Buffer {" NL "  uvec4 u[4];" NL
2548                "  ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2549                "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y][2]);" NL
2550                "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y][1]);" NL
2551                "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y].z);" NL
2552                "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y].y);" NL "}";
2553         m_program = CreateProgramCS(glsl_cs);
2554         glLinkProgram(m_program);
2555         if (!CheckProgram(m_program))
2556             return ERROR;
2557 
2558         /* init storage buffer */
2559         {
2560             glGenBuffers(1, &m_storage_buffer);
2561             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2562             glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2563             ivec4 *ptr = reinterpret_cast<ivec4 *>(
2564                 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2565             if (!ptr)
2566                 return ERROR;
2567             for (int i = 0; i < 4; ++i)
2568             {
2569                 ptr[i * 2]     = ivec4(0, 1, 2, 0);
2570                 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2571             }
2572             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2573         }
2574 
2575         glUseProgram(m_program);
2576         glDispatchCompute(1, 1, 1);
2577         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2578 
2579         GLuint *u = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2580         if (!u)
2581             return ERROR;
2582         if (*u != 16)
2583         {
2584             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2585                                                 << " should be 16." << tcu::TestLog::EndMessage;
2586             return ERROR;
2587         }
2588         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2589         GLint *i = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2590         if (!i)
2591             return ERROR;
2592         if (*i != 16)
2593         {
2594             m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2595                                                 << " should be 16." << tcu::TestLog::EndMessage;
2596             return ERROR;
2597         }
2598         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2599 
2600         return NO_ERROR;
2601     }
2602 
Cleanup()2603     virtual long Cleanup()
2604     {
2605         glUseProgram(0);
2606         glDeleteProgram(m_program);
2607         glDeleteBuffers(1, &m_storage_buffer);
2608         return NO_ERROR;
2609     }
2610 };
2611 
2612 //-----------------------------------------------------------------------------
2613 // 1.8.4 BasicAtomicCase4
2614 //-----------------------------------------------------------------------------
2615 class BasicAtomicCase4VSFS : public ShaderStorageBufferObjectBase
2616 {
2617     GLuint m_program;
2618     GLuint m_storage_buffer[2];
2619     GLuint m_vertex_array;
2620     GLuint m_vertex_buffer;
2621 
Setup()2622     virtual long Setup()
2623     {
2624         m_program = 0;
2625         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2626         m_vertex_array  = 0;
2627         m_vertex_buffer = 0;
2628         return NO_ERROR;
2629     }
2630 
Run()2631     virtual long Run()
2632     {
2633         if (!IsVSFSAvailable(2, 2))
2634             return NOT_SUPPORTED;
2635         const char *const glsl_vs =
2636             NL "layout(location = 0) in vec4 g_in_position;" NL
2637                "layout(std430, binding = 0) coherent buffer Counters {" NL "  uint g_uint_counter;" NL
2638                "  int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL
2639                "  int idata[8];" NL "} g_output;" NL "void main() {" NL "  gl_Position = g_in_position;" NL
2640                "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL
2641                "  uint uidx = atomicAdd(g_uint_counter, 1u);" NL "  int iidx = atomicAdd(g_int_counter, -1);" NL
2642                "  g_output.udata[uidx] = uidx;" NL "  g_output.idata[iidx] = iidx;" NL "}";
2643         const char *const glsl_fs =
2644             NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) coherent buffer Counters {" NL
2645                "  uint g_uint_counter;" NL "  int g_int_counter;" NL "};" NL
2646                "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL "  int idata[8];" NL
2647                "} g_output;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL
2648                "  uint uidx = atomicAdd(g_uint_counter, 1u);" NL "  int iidx = atomicAdd(g_int_counter, -1);" NL
2649                "  g_output.udata[uidx] = uidx;" NL "  g_output.idata[iidx] = iidx;" NL "}";
2650         m_program = CreateProgram(glsl_vs, glsl_fs);
2651         glLinkProgram(m_program);
2652         if (!CheckProgram(m_program))
2653             return ERROR;
2654 
2655         glGenBuffers(2, m_storage_buffer);
2656         /* counter buffer */
2657         {
2658             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2659             glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2660             int *ptr = reinterpret_cast<int *>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
2661             if (!ptr)
2662                 return ERROR;
2663             *ptr++ = 0;
2664             *ptr++ = 7;
2665             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2666         }
2667         /* output buffer */
2668         {
2669             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2670             glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2671         }
2672         /* vertex buffer */
2673         {
2674             const float data[] = {-0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f};
2675             glGenBuffers(1, &m_vertex_buffer);
2676             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2677             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2678             glBindBuffer(GL_ARRAY_BUFFER, 0);
2679         }
2680 
2681         glGenVertexArrays(1, &m_vertex_array);
2682         glBindVertexArray(m_vertex_array);
2683         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2684         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2685         glBindBuffer(GL_ARRAY_BUFFER, 0);
2686         glEnableVertexAttribArray(0);
2687         glBindVertexArray(0);
2688 
2689         glClear(GL_COLOR_BUFFER_BIT);
2690         glUseProgram(m_program);
2691         glBindVertexArray(m_vertex_array);
2692         glDrawArrays(GL_POINTS, 0, 4);
2693         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2694 
2695         GLuint *udata = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2696         if (!udata)
2697             return ERROR;
2698         for (GLuint i = 0; i < 8; ++i)
2699         {
2700             if (udata[i] != i)
2701             {
2702                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2703                                                     << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2704                 return ERROR;
2705             }
2706         }
2707         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2708         GLint *idata = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2709         if (!idata)
2710             return ERROR;
2711         for (GLint i = 0; i < 8; ++i)
2712         {
2713             if (idata[i] != i)
2714             {
2715                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2716                                                     << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2717                 return ERROR;
2718             }
2719         }
2720         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2721         return NO_ERROR;
2722     }
2723 
Cleanup()2724     virtual long Cleanup()
2725     {
2726         glUseProgram(0);
2727         glDeleteProgram(m_program);
2728         glDeleteBuffers(2, m_storage_buffer);
2729         glDeleteBuffers(1, &m_vertex_buffer);
2730         glDeleteVertexArrays(1, &m_vertex_array);
2731         return NO_ERROR;
2732     }
2733 };
2734 
2735 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2736 {
2737     GLuint m_program;
2738     GLuint m_storage_buffer[2];
2739 
Setup()2740     virtual long Setup()
2741     {
2742         m_program = 0;
2743         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2744         return NO_ERROR;
2745     }
2746 
Run()2747     virtual long Run()
2748     {
2749         const char *const glsl_cs =
2750             NL "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;" NL
2751                "layout(std430, binding = 0) coherent buffer Counters {" NL "  uint g_uint_counter;" NL
2752                "  int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL
2753                "  int idata[8];" NL "} g_output;" NL "void main() {" NL
2754                "  uint uidx = atomicAdd(g_uint_counter, 1u);" NL "  int iidx = atomicAdd(g_int_counter, -1);" NL
2755                "  g_output.udata[uidx] = uidx;" NL "  g_output.idata[iidx] = iidx;" NL "}";
2756         m_program = CreateProgramCS(glsl_cs);
2757         glLinkProgram(m_program);
2758         if (!CheckProgram(m_program))
2759             return ERROR;
2760 
2761         glGenBuffers(2, m_storage_buffer);
2762         /* counter buffer */
2763         {
2764             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2765             glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2766             int *ptr = reinterpret_cast<int *>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
2767             if (!ptr)
2768                 return ERROR;
2769             *ptr++ = 0;
2770             *ptr++ = 7;
2771             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2772         }
2773         /* output buffer */
2774         {
2775             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2776             glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2777         }
2778         glUseProgram(m_program);
2779         glDispatchCompute(1, 1, 1);
2780         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2781 
2782         GLuint *udata = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2783         if (!udata)
2784             return ERROR;
2785         for (GLuint i = 0; i < 8; ++i)
2786         {
2787             if (udata[i] != i)
2788             {
2789                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2790                                                     << udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2791                 return ERROR;
2792             }
2793         }
2794         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2795         GLint *idata = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2796         if (!idata)
2797             return ERROR;
2798         for (GLint i = 0; i < 8; ++i)
2799         {
2800             if (idata[i] != i)
2801             {
2802                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2803                                                     << idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2804                 return ERROR;
2805             }
2806         }
2807         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2808         return NO_ERROR;
2809     }
2810 
Cleanup()2811     virtual long Cleanup()
2812     {
2813         glUseProgram(0);
2814         glDeleteProgram(m_program);
2815         glDeleteBuffers(2, m_storage_buffer);
2816         return NO_ERROR;
2817     }
2818 };
2819 //-----------------------------------------------------------------------------
2820 // 1.9.x BasicStdLayoutBase2
2821 //-----------------------------------------------------------------------------
2822 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
2823 {
2824     GLuint m_program;
2825     GLuint m_buffer[8];
2826     GLuint m_vertex_array;
2827 
2828     virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
2829 
Setup()2830     virtual long Setup()
2831     {
2832         m_program = 0;
2833         memset(m_buffer, 0, sizeof(m_buffer));
2834         m_vertex_array = 0;
2835         return NO_ERROR;
2836     }
2837 
Run()2838     virtual long Run()
2839     {
2840         if (!IsVSFSAvailable(8, 0))
2841             return NOT_SUPPORTED;
2842         std::vector<GLubyte> in_data[4];
2843         const char *glsl_vs       = GetInput(in_data);
2844         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
2845                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
2846 
2847         m_program = CreateProgram(glsl_vs, glsl_fs);
2848         glLinkProgram(m_program);
2849         if (!CheckProgram(m_program))
2850             return ERROR;
2851 
2852         glGenBuffers(8, m_buffer);
2853 
2854         for (GLuint i = 0; i < 4; ++i)
2855         {
2856             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
2857             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
2858 
2859             std::vector<GLubyte> out_data(in_data[i].size());
2860             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
2861             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
2862         }
2863 
2864         glGenVertexArrays(1, &m_vertex_array);
2865         glEnable(GL_RASTERIZER_DISCARD);
2866 
2867         glUseProgram(m_program);
2868         glBindVertexArray(m_vertex_array);
2869         glDrawArrays(GL_POINTS, 0, 1);
2870 
2871         bool status = true;
2872         for (int j = 0; j < 4; ++j)
2873         {
2874             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2875             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2876             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
2877                                                             GL_MAP_READ_BIT);
2878             if (!out_data)
2879                 return ERROR;
2880 
2881             for (size_t i = 0; i < in_data[j].size(); ++i)
2882             {
2883                 if (in_data[j][i] != out_data[i])
2884                 {
2885                     m_context.getTestContext().getLog()
2886                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
2887                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
2888                         << tcu::TestLog::EndMessage;
2889                     status = false;
2890                 }
2891             }
2892             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2893         }
2894         if (!status)
2895             return ERROR;
2896         return NO_ERROR;
2897     }
2898 
Cleanup()2899     virtual long Cleanup()
2900     {
2901         glDisable(GL_RASTERIZER_DISCARD);
2902         glUseProgram(0);
2903         glDeleteProgram(m_program);
2904         glDeleteBuffers(8, m_buffer);
2905         glDeleteVertexArrays(1, &m_vertex_array);
2906         return NO_ERROR;
2907     }
2908 };
2909 
2910 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
2911 {
2912     GLuint m_program;
2913     GLuint m_buffer[8];
2914 
2915     virtual const char *GetInput(std::vector<GLubyte> in_data[4]) = 0;
2916 
Setup()2917     virtual long Setup()
2918     {
2919         m_program = 0;
2920         memset(m_buffer, 0, sizeof(m_buffer));
2921         return NO_ERROR;
2922     }
2923 
Run()2924     virtual long Run()
2925     {
2926         std::vector<GLubyte> in_data[4];
2927         std::stringstream ss;
2928         GLint blocksCS;
2929         glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
2930         if (blocksCS < 8)
2931             return NO_ERROR;
2932         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
2933         m_program = CreateProgramCS(ss.str());
2934         glLinkProgram(m_program);
2935         if (!CheckProgram(m_program))
2936             return ERROR;
2937 
2938         glGenBuffers(8, m_buffer);
2939 
2940         for (GLuint i = 0; i < 4; ++i)
2941         {
2942             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
2943             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
2944 
2945             std::vector<GLubyte> out_data(in_data[i].size());
2946             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
2947             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
2948         }
2949 
2950         glUseProgram(m_program);
2951         glDispatchCompute(1, 1, 1);
2952         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2953 
2954         bool status = true;
2955         for (int j = 0; j < 4; ++j)
2956         {
2957             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2958             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
2959                                                             GL_MAP_READ_BIT);
2960             if (!out_data)
2961                 return ERROR;
2962 
2963             for (size_t i = 0; i < in_data[j].size(); ++i)
2964             {
2965                 if (in_data[j][i] != out_data[i])
2966                 {
2967                     m_context.getTestContext().getLog()
2968                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
2969                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
2970                         << tcu::TestLog::EndMessage;
2971                     status = false;
2972                 }
2973             }
2974             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2975         }
2976         if (!status)
2977             return ERROR;
2978         return NO_ERROR;
2979     }
2980 
Cleanup()2981     virtual long Cleanup()
2982     {
2983         glUseProgram(0);
2984         glDeleteProgram(m_program);
2985         glDeleteBuffers(8, m_buffer);
2986         return NO_ERROR;
2987     }
2988 };
2989 
2990 //-----------------------------------------------------------------------------
2991 // 1.9.1 BasicStdLayoutCase1
2992 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])2993 const char *GetInputC1(std::vector<GLubyte> in_data[4])
2994 {
2995     for (int i = 0; i < 4; ++i)
2996     {
2997         in_data[i].resize(1 * 4);
2998         float *fp = reinterpret_cast<float *>(&in_data[i][0]);
2999         fp[0]     = (float)(i + 1) * 1.0f;
3000     }
3001     return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
3002               "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
3003               "void main() {" NL "    g_output[0].data0 = g_input[0].data0;" NL
3004               "    g_output[1].data0 = g_input[1].data0;" NL "    g_output[2].data0 = g_input[2].data0;" NL
3005               "    g_output[3].data0 = g_input[3].data0;" NL "}";
3006 }
3007 
3008 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3009 {
GetInput(std::vector<GLubyte> in_data[4])3010     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3011     {
3012         return GetInputC1(in_data);
3013     }
3014 };
3015 
3016 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3017 {
GetInput(std::vector<GLubyte> in_data[4])3018     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3019     {
3020         return GetInputC1(in_data);
3021     }
3022 };
3023 
3024 //-----------------------------------------------------------------------------
3025 // 1.9.2 BasicStdLayoutCase2
3026 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3027 const char *GetInputC2(std::vector<GLubyte> in_data[4])
3028 {
3029     /* input 0, std140 */
3030     {
3031         in_data[0].resize(12 * 4);
3032         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3033         fp[0]     = 1.0f;
3034         fp[1]     = 0.0f;
3035         fp[2]     = 0.0f;
3036         fp[3]     = 0.0f;
3037         fp[4]     = 2.0f;
3038         fp[5]     = 0.0f;
3039         fp[6]     = 0.0f;
3040         fp[7]     = 0.0f;
3041         fp[8]     = 3.0f;
3042         fp[9]     = 0.0f;
3043         fp[10]    = 0.0f;
3044         fp[11]    = 0.0f;
3045     }
3046     /* input 1, std430 */
3047     {
3048         in_data[1].resize(3 * 4);
3049         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3050         fp[0]     = 4.0f;
3051         fp[1]     = 5.0f;
3052         fp[2]     = 6.0f;
3053     }
3054     /* input 2, std140 */
3055     {
3056         in_data[2].resize(12 * 4);
3057         float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3058         fp[0]     = 7.0f;
3059         fp[1]     = 0.0f;
3060         fp[2]     = 0.0f;
3061         fp[3]     = 0.0f;
3062         fp[4]     = 8.0f;
3063         fp[5]     = 0.0f;
3064         fp[6]     = 0.0f;
3065         fp[7]     = 0.0f;
3066         fp[8]     = 9.0f;
3067         fp[9]     = 0.0f;
3068         fp[10]    = 0.0f;
3069         fp[11]    = 0.0f;
3070     }
3071     /* input 3, std430 */
3072     {
3073         in_data[3].resize(3 * 4);
3074         float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3075         fp[0]     = 10.0f;
3076         fp[1]     = 11.0f;
3077         fp[2]     = 12.0f;
3078     }
3079     return NL "layout(std140, binding = 0) buffer Input0 {" NL "  float data0[3];" NL "} g_input0;" NL
3080               "layout(std430, binding = 1) buffer Input1 {" NL "  float data0[3];" NL "} g_input1;" NL
3081               "layout(std140, binding = 2) buffer Input2 {" NL "  float data0[3];" NL "} g_input2;" NL
3082               "layout(std430, binding = 3) buffer Input3 {" NL "  float data0[3];" NL "} g_input3;" NL
3083               "layout(std140, binding = 4) buffer Output0 {" NL "  float data0[3];" NL "} g_output0;" NL
3084               "layout(std430, binding = 5) buffer Output1 {" NL "  float data0[3];" NL "} g_output1;" NL
3085               "layout(std140, binding = 6) buffer Output2 {" NL "  float data0[3];" NL "} g_output2;" NL
3086               "layout(std430, binding = 7) buffer Output3 {" NL "  float data0[3];" NL "} g_output3;" NL
3087               "void main() {" NL
3088               "  for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3089               "  for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3090               "  for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3091               "  for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3092 }
3093 
3094 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3095 {
GetInput(std::vector<GLubyte> in_data[4])3096     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3097     {
3098         return GetInputC2(in_data);
3099     }
3100 };
3101 
3102 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3103 {
GetInput(std::vector<GLubyte> in_data[4])3104     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3105     {
3106         return GetInputC2(in_data);
3107     }
3108 };
3109 
3110 //-----------------------------------------------------------------------------
3111 // 1.9.3 BasicStdLayoutCase3
3112 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3113 const char *GetInputC3(std::vector<GLubyte> in_data[4])
3114 {
3115     /* input 0, std140 */
3116     {
3117         in_data[0].resize(62 * 4);
3118         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3119         int *ip   = reinterpret_cast<int *>(&in_data[0][0]);
3120         ip[0]     = 1;
3121         ip[1]     = 0;
3122         ip[2]     = 0;
3123         ip[3]     = 0;
3124         fp[4]     = 2.0f;
3125         fp[5]     = 0.0f;
3126         fp[6]     = 0.0f;
3127         fp[7]     = 0.0f;
3128         fp[8]     = 3.0f;
3129         fp[9]     = 0.0f;
3130         fp[10]    = 0.0f;
3131         fp[11]    = 0.0f;
3132         fp[12]    = 4.0f;
3133         fp[13]    = 0.0f;
3134         fp[14]    = 0.0f;
3135         fp[15]    = 0.0f;
3136         fp[16]    = 5.0f;
3137         fp[17]    = 0.0f;
3138         fp[18]    = 0.0f;
3139         fp[19]    = 0.0f;
3140         fp[20]    = 6.0f;
3141         fp[21]    = 0.0f;
3142         fp[22]    = 0.0f;
3143         fp[23]    = 0.0f;
3144         fp[24]    = 7.0f;
3145         fp[25]    = 8.0f;
3146         fp[26]    = 0.0f;
3147         fp[27]    = 0.0f;
3148         fp[28]    = 9.0f;
3149         fp[29]    = 10.0f;
3150         fp[30]    = 0.0f;
3151         fp[31]    = 0.0f;
3152         fp[32]    = 11.0f;
3153         fp[33]    = 12.0f;
3154         fp[34]    = 0.0f;
3155         fp[35]    = 0.0f;
3156         fp[36]    = 13.0f;
3157         fp[37]    = 0.0f;
3158         fp[38]    = 0.0f;
3159         fp[39]    = 0.0f;
3160         fp[40]    = 14.0f;
3161         fp[41]    = 0.0f;
3162         fp[42]    = 0.0f;
3163         fp[43]    = 0.0f;
3164         fp[44]    = 15.0f;
3165         fp[45]    = 0.0f;
3166         fp[46]    = 0.0f;
3167         fp[47]    = 0.0f;
3168         ip[48]    = 16;
3169         ip[49]    = 0;
3170         ip[50]    = 0;
3171         ip[51]    = 0;
3172         ip[52]    = 17;
3173         ip[53]    = 18;
3174         ip[54]    = 19;
3175         ip[55]    = 0;
3176     }
3177     /* input 1, std430 */
3178     {
3179         in_data[1].resize(30 * 4);
3180         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3181         int *ip   = reinterpret_cast<int *>(&in_data[1][0]);
3182         ip[0]     = 1;
3183         fp[1]     = 2.0f;
3184         fp[2]     = 3.0f;
3185         fp[3]     = 4.0f;
3186         fp[4]     = 5.0f;
3187         fp[5]     = 6.0f;
3188         fp[6]     = 7.0f;
3189         fp[7]     = 8.0f;
3190         fp[8]     = 9.0f;
3191         fp[9]     = 10.0f;
3192         fp[10]    = 11.0f;
3193         fp[11]    = 12.0f;
3194         fp[12]    = 13.0f;
3195         fp[13]    = 14.0f;
3196         fp[14]    = 15.0f;
3197         ip[15]    = 16;
3198         ip[16]    = 17;
3199         ip[17]    = 18;
3200         ip[18]    = 19;
3201     }
3202     /* input 2, std140 */
3203     {
3204         in_data[2].resize(5 * 4);
3205         int *ip = reinterpret_cast<int *>(&in_data[2][0]);
3206         ip[0]   = 1;
3207         ip[1]   = 0;
3208         ip[2]   = 0;
3209         ip[3]   = 0;
3210         ip[4]   = 2;
3211     }
3212     /* input 3, std430 */
3213     {
3214         in_data[3].resize(2 * 4);
3215         int *ip = reinterpret_cast<int *>(&in_data[3][0]);
3216         ip[0]   = 1;
3217         ip[1]   = 2;
3218     }
3219     return NL "layout(std140, binding = 0) buffer Input0 {" NL "  int data0;"               //BA=4,  OF=[0]0,   next=4
3220         NL "  float data1[5];"                                                              //BA=16, OF=[4]16,  next=96
3221         NL "  mat3x2 data2;"                                                                //BA=16, OF=[24]96, next=144
3222         NL "  float data3;"                                                                 //BA=4,  OF=[36]144,next=148
3223         NL "  float data4[2];"                                                              //BA=16, OF=[40]160,next=192
3224         NL "  int data5;"                                                                   //BA=4,  OF=[48]192,next=196
3225         NL "  ivec3 data6;"                                                                 //BA=16, OF=[52]208
3226         NL "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL "  int data0;" //BA=4, OF=[0],   next=[1]
3227         NL "  float data1[5];"                                                              //BA=4, OF=[1],   next=[6]
3228         NL "  mat3x2 data2;"                                                                //BA=8, OF=[6],   next=[12]
3229         NL "  float data3;"                                                                 //BA=4, OF=[12],  next=[13]
3230         NL "  float data4[2];"                                                              //BA=4, OF=[13],  next=[15]
3231         NL "  int data5;"                                                                   //BA=4, OF=[15],  next=[16]
3232         NL "  ivec3 data6;"                                                                 //BA=16,OF=[16]
3233         NL "} g_input1;" NL "struct Struct0 {" NL "  int data0;" NL "};" NL
3234               "layout(std140, binding = 2) buffer Input2 {" NL "  int data0;" // offset 0
3235         NL "  Struct0 data1;" // offset 16,  struct should be aligned to a multiple of 16 bytes
3236         NL "} g_input2;" NL "layout(std430, binding = 3) buffer Input3 {" NL "  int data0;" // offset 0
3237         NL "  Struct0 data1;"                                                               // offset 4
3238         NL "} g_input3;"
3239 
3240         NL "layout(std140, binding = 4) buffer Output0 {" NL "  int data0;" NL "  float data1[5];" NL
3241               "  mat3x2 data2;" NL "  float data3;" NL "  float data4[2];" NL "  int data5;" NL "  ivec3 data6;" NL
3242               "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL "  int data0;" NL
3243               "  float data1[5];" NL "  mat3x2 data2;" NL "  float data3;" NL "  float data4[2];" NL "  int data5;" NL
3244               "  ivec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL "  int data0;" NL
3245               "  Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3246               "  int data0;" NL "  Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3247               "  g_output0.data0 = g_input0.data0;" NL
3248               "  for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3249               "  g_output0.data2 = g_input0.data2;" NL "  g_output0.data3 = g_input0.data3;" NL
3250               "  for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3251               "  g_output0.data5 = g_input0.data5;" NL "  g_output0.data6 = g_input0.data6;"
3252 
3253         NL "  g_output1.data0 = g_input1.data0;" NL
3254               "  for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3255               "  g_output1.data2 = g_input1.data2;" NL "  g_output1.data3 = g_input1.data3;" NL
3256               "  for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3257               "  g_output1.data5 = g_input1.data5;" NL "  g_output1.data6 = g_input1.data6;"
3258 
3259         NL "  g_output2.data0 = g_input2.data0;" NL "  g_output2.data1 = g_input2.data1;"
3260 
3261         NL "  g_output3.data0 = g_input3.data0;" NL "  g_output3.data1 = g_input3.data1;" NL "}";
3262 }
3263 
3264 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3265 {
GetInput(std::vector<GLubyte> in_data[4])3266     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3267     {
3268         return GetInputC3(in_data);
3269     }
3270 };
3271 
3272 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3273 {
GetInput(std::vector<GLubyte> in_data[4])3274     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3275     {
3276         return GetInputC3(in_data);
3277     }
3278 };
3279 
3280 //-----------------------------------------------------------------------------
3281 // 1.9.4 BasicStdLayoutCase4
3282 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3283 const char *GetInputC4(std::vector<GLubyte> in_data[4])
3284 {
3285     /* input 0, std140 */
3286     {
3287         in_data[0].resize(57 * 4);
3288         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
3289         int *ip   = reinterpret_cast<int *>(&in_data[0][0]);
3290         ip[0]     = 1;
3291         ip[1]     = 0;
3292         ip[2]     = 0;
3293         ip[3]     = 0;
3294         ip[4]     = 2;
3295         ip[5]     = 3;
3296         ip[6]     = 0;
3297         ip[7]     = 0;
3298         ip[8]     = 4;
3299         ip[9]     = 5;
3300         ip[10]    = 0;
3301         ip[11]    = 0;
3302         fp[12]    = 6.0f;
3303         fp[13]    = 0.0f;
3304         fp[14]    = 0.0f;
3305         fp[15]    = 0.0f;
3306         fp[16]    = 7.0f;
3307         fp[17]    = 8.0f;
3308         fp[18]    = 0.0f;
3309         fp[19]    = 0.0f;
3310         ip[20]    = 9;
3311         ip[21]    = 10;
3312         ip[22]    = 11;
3313         ip[23]    = 0;
3314         fp[24]    = 12.0f;
3315         fp[25]    = 13.0f;
3316         fp[26]    = 0.0f;
3317         fp[27]    = 0.0f;
3318         ip[28]    = 14;
3319         ip[29]    = 15;
3320         ip[30]    = 16;
3321         ip[31]    = 0;
3322         fp[32]    = 17.0f;
3323         fp[33]    = 0.0f;
3324         fp[34]    = 0.0f;
3325         fp[35]    = 0.0f;
3326         ip[36]    = 18;
3327         ip[37]    = 0;
3328         ip[38]    = 0;
3329         ip[39]    = 0;
3330         ip[40]    = 19;
3331         ip[41]    = 20;
3332         ip[42]    = 0;
3333         ip[43]    = 0;
3334         ip[44]    = 21;
3335         ip[45]    = 0;
3336         ip[45]    = 0;
3337         ip[45]    = 0;
3338         fp[48]    = 22.0f;
3339         fp[49]    = 23.0f;
3340         fp[50]    = 0.0f;
3341         fp[51]    = 0.0f;
3342         ip[52]    = 24;
3343         ip[53]    = 25;
3344         ip[54]    = 26;
3345         ip[55]    = 0;
3346         fp[56]    = 27.0f;
3347     }
3348     /* input 1, std140 */
3349     {
3350         in_data[1].resize(57 * 4);
3351         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
3352         int *ip   = reinterpret_cast<int *>(&in_data[1][0]);
3353         ip[0]     = 101;
3354         ip[1]     = 0;
3355         ip[2]     = 0;
3356         ip[3]     = 0;
3357         ip[4]     = 102;
3358         ip[5]     = 103;
3359         ip[6]     = 0;
3360         ip[7]     = 0;
3361         ip[8]     = 104;
3362         ip[9]     = 105;
3363         ip[10]    = 0;
3364         ip[11]    = 0;
3365         fp[12]    = 106.0f;
3366         fp[13]    = 0.0f;
3367         fp[14]    = 0.0f;
3368         fp[15]    = 0.0f;
3369         fp[16]    = 107.0f;
3370         fp[17]    = 108.0f;
3371         fp[18]    = 0.0f;
3372         fp[19]    = 0.0f;
3373         ip[20]    = 109;
3374         ip[21]    = 110;
3375         ip[22]    = 111;
3376         ip[23]    = 0;
3377         fp[24]    = 112.0f;
3378         fp[25]    = 113.0f;
3379         fp[26]    = 0.0f;
3380         fp[27]    = 0.0f;
3381         ip[28]    = 114;
3382         ip[29]    = 115;
3383         ip[30]    = 116;
3384         ip[31]    = 0;
3385         fp[32]    = 117.0f;
3386         fp[33]    = 0.0f;
3387         fp[34]    = 0.0f;
3388         fp[35]    = 0.0f;
3389         ip[36]    = 118;
3390         ip[37]    = 0;
3391         ip[38]    = 0;
3392         ip[39]    = 0;
3393         ip[40]    = 119;
3394         ip[41]    = 120;
3395         ip[42]    = 0;
3396         ip[43]    = 0;
3397         ip[44]    = 121;
3398         ip[45]    = 0;
3399         ip[45]    = 0;
3400         ip[45]    = 0;
3401         fp[48]    = 122.0f;
3402         fp[49]    = 123.0f;
3403         fp[50]    = 0.0f;
3404         fp[51]    = 0.0f;
3405         ip[52]    = 124;
3406         ip[53]    = 125;
3407         ip[54]    = 126;
3408         ip[55]    = 0;
3409         fp[56]    = 127.0f;
3410     }
3411     /* input 2, std430 */
3412     {
3413         in_data[2].resize(45 * 4);
3414         float *fp = reinterpret_cast<float *>(&in_data[2][0]);
3415         int *ip   = reinterpret_cast<int *>(&in_data[2][0]);
3416         ip[0]     = 1000;
3417         ip[1]     = 0;
3418         ip[2]     = 1001;
3419         ip[3]     = 1002;
3420         ip[4]     = 1003;
3421         ip[5]     = 1004;
3422         fp[6]     = 1005.0f;
3423         fp[7]     = 0.0f;
3424         fp[8]     = 1006.0f;
3425         fp[9]     = 1007.0f;
3426         fp[10]    = 0.0f;
3427         fp[11]    = 0.0f;
3428         ip[12]    = 1008;
3429         ip[13]    = 1009;
3430         ip[14]    = 1010;
3431         ip[15]    = 0;
3432         fp[16]    = 1011.0f;
3433         fp[17]    = 1012.0f;
3434         fp[18]    = 0.0f;
3435         fp[19]    = 0.0f;
3436         ip[20]    = 1013;
3437         ip[21]    = 1014;
3438         ip[22]    = 1015;
3439         ip[23]    = 0;
3440         fp[24]    = 1016.0f;
3441         fp[25]    = 0.0f;
3442         fp[26]    = 0.0f;
3443         fp[27]    = 0.0f;
3444         ip[28]    = 1017;
3445         ip[29]    = 0;
3446         ip[30]    = 1018;
3447         ip[31]    = 1019;
3448         ip[32]    = 1020;
3449         ip[33]    = 0;
3450         ip[34]    = 0;
3451         ip[35]    = 0;
3452         fp[36]    = 1021.0f;
3453         fp[37]    = 1022.0f;
3454         fp[38]    = 0.0f;
3455         fp[39]    = 0.0f;
3456         ip[40]    = 1023;
3457         ip[41]    = 1024;
3458         ip[42]    = 1025;
3459         ip[43]    = 0;
3460         fp[44]    = 1026.0f;
3461     }
3462     /* input 3, std430 */
3463     {
3464         in_data[3].resize(45 * 4);
3465         float *fp = reinterpret_cast<float *>(&in_data[3][0]);
3466         int *ip   = reinterpret_cast<int *>(&in_data[3][0]);
3467         ip[0]     = 10000;
3468         ip[1]     = 0;
3469         ip[2]     = 10001;
3470         ip[3]     = 10002;
3471         ip[4]     = 10003;
3472         ip[5]     = 10004;
3473         fp[6]     = 10005.0f;
3474         fp[7]     = 0.0f;
3475         fp[8]     = 10006.0f;
3476         fp[9]     = 10007.0f;
3477         fp[10]    = 0.0f;
3478         fp[11]    = 0.0f;
3479         ip[12]    = 10008;
3480         ip[13]    = 10009;
3481         ip[14]    = 10010;
3482         ip[15]    = 0;
3483         fp[16]    = 10011.0f;
3484         fp[17]    = 10012.0f;
3485         fp[18]    = 0.0f;
3486         fp[19]    = 0.0f;
3487         ip[20]    = 10013;
3488         ip[21]    = 10014;
3489         ip[22]    = 10015;
3490         ip[23]    = 0;
3491         fp[24]    = 10016.0f;
3492         fp[25]    = 0.0f;
3493         fp[26]    = 0.0f;
3494         fp[27]    = 0.0f;
3495         ip[28]    = 10017;
3496         ip[29]    = 0;
3497         ip[30]    = 10018;
3498         ip[31]    = 10019;
3499         ip[32]    = 10020;
3500         ip[33]    = 0;
3501         ip[34]    = 0;
3502         ip[35]    = 0;
3503         fp[36]    = 10021.0f;
3504         fp[37]    = 10022.0f;
3505         fp[38]    = 0.0f;
3506         fp[39]    = 0.0f;
3507         ip[40]    = 10023;
3508         ip[41]    = 10024;
3509         ip[42]    = 10025;
3510         ip[43]    = 0;
3511         fp[44]    = 10026.0f;
3512     }
3513 
3514     return NL
3515         "struct Struct0 {" NL "  ivec2 data0;" NL "};" NL "struct Struct1 {" NL "  vec2 data0;" // offset 0
3516         NL "  ivec3 data1;"                                                                     // offset 16
3517         NL "};" NL "struct Struct2 {" NL "  int data0;"                                         // offset 0
3518         NL "  Struct0 data1;"                                                       // offset std430 8, std140 16
3519         NL "  int data2;"                                                           // offset std430 16, std140 32
3520         NL "  Struct1 data3;"                                                       // offset std430 32, std140 48
3521         NL "  float data4;"                                                         // offset std430 64, std140 80
3522         NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL "  int data0;" // offset 0
3523         NL "  Struct0 data1[2];"                                                    // offset 16
3524         NL "  float data2;"                                                         // offset 48
3525         NL "  Struct1 data3[2];"                                                    // offset 64
3526         NL "  float data4;"                                                         // offset 128
3527         NL "  Struct2 data5;"                                                       // offset 144
3528         NL "} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL "  int data0;" // offset 0
3529         NL "  Struct0 data1[2];"                                                                 // offset 8
3530         NL "  float data2;"                                                                      // offset 24
3531         NL "  Struct1 data3[2];"                                                                 // offset 32
3532         NL "  float data4;"                                                                      // offset 96
3533         NL "  Struct2 data5;"                                                                    // offset 112
3534         NL "} g_input23[2];"
3535 
3536         NL "layout(std140, binding = 4) buffer Output01 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3537         "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output01[2];" NL
3538         "layout(std430, binding = 6) buffer Output23 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3539         "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output23[2];" NL NL
3540         "void main() {" NL "  g_output01[0].data0 = g_input01[0].data0;" NL
3541         "  for (int i = 0; i < g_input01[0].data1.length(); ++i) g_output01[0].data1[i] = g_input01[0].data1[i];" NL
3542         "  g_output01[0].data2 = g_input01[0].data2;" NL "  g_output01[0].data3[0] = g_input01[0].data3[0];" NL
3543         "  g_output01[0].data3[1] = g_input01[0].data3[1];" NL "  g_output01[0].data4 = g_input01[0].data4;" NL
3544         "  g_output01[1].data0 = g_input01[1].data0;" NL
3545         "  for (int i = 0; i < g_input01[1].data1.length(); ++i) g_output01[1].data1[i] = g_input01[1].data1[i];" NL
3546         "  g_output01[1].data2 = g_input01[1].data2;" NL "  g_output01[1].data3[0] = g_input01[1].data3[0];" NL
3547         "  g_output01[1].data3[1] = g_input01[1].data3[1];" NL "  g_output01[1].data4 = g_input01[1].data4;" NL
3548         "  g_output01[0].data5 = g_input01[0].data5;" NL "  g_output01[1].data5 = g_input01[1].data5;" NL NL
3549         "  g_output23[0].data0 = g_input23[0].data0;" NL
3550         "  for (int i = 0; i < g_input23[0].data1.length(); ++i) g_output23[0].data1[i] = g_input23[0].data1[i];" NL
3551         "  g_output23[0].data2 = g_input23[0].data2;" NL "  g_output23[0].data3[0] = g_input23[0].data3[0];" NL
3552         "  g_output23[0].data3[1] = g_input23[0].data3[1];" NL "  g_output23[0].data4 = g_input23[0].data4;" NL
3553         "  g_output23[1].data0 = g_input23[1].data0;" NL
3554         "  for (int i = 0; i < g_input23[1].data1.length(); ++i) g_output23[1].data1[i] = g_input23[1].data1[i];" NL
3555         "  g_output23[1].data2 = g_input23[1].data2;" NL "  g_output23[1].data3[0] = g_input23[1].data3[0];" NL
3556         "  g_output23[1].data3[1] = g_input23[1].data3[1];" NL "  g_output23[1].data4 = g_input23[1].data4;" NL
3557         "  g_output23[0].data5 = g_input23[0].data5;" NL "  g_output23[1].data5 = g_input23[1].data5;" NL "}";
3558 }
3559 
3560 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3561 {
GetInput(std::vector<GLubyte> in_data[4])3562     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3563     {
3564         return GetInputC4(in_data);
3565     }
3566 };
3567 
3568 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3569 {
GetInput(std::vector<GLubyte> in_data[4])3570     virtual const char *GetInput(std::vector<GLubyte> in_data[4])
3571     {
3572         return GetInputC4(in_data);
3573     }
3574 };
3575 
3576 //-----------------------------------------------------------------------------
3577 // 1.10.x BasicOperationsBase
3578 //-----------------------------------------------------------------------------
3579 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3580 {
3581     GLuint m_program;
3582     GLuint m_buffer[2];
3583     GLuint m_vertex_array;
3584 
3585     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3586 
Setup()3587     virtual long Setup()
3588     {
3589         m_program = 0;
3590         memset(m_buffer, 0, sizeof(m_buffer));
3591         m_vertex_array = 0;
3592         return NO_ERROR;
3593     }
3594 
Run()3595     virtual long Run()
3596     {
3597         if (!IsVSFSAvailable(2, 0))
3598             return NOT_SUPPORTED;
3599         std::vector<GLubyte> in_data;
3600         std::vector<GLubyte> expected_data;
3601         const char *glsl_vs       = GetInput(in_data, expected_data);
3602         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
3603                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
3604 
3605         m_program = CreateProgram(glsl_vs, glsl_fs);
3606         glLinkProgram(m_program);
3607         if (!CheckProgram(m_program))
3608             return ERROR;
3609 
3610         glGenBuffers(2, m_buffer);
3611 
3612         /* output buffer */
3613         {
3614             std::vector<GLubyte> zero(expected_data.size());
3615             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3616             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3617         }
3618         // input buffer
3619         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3620         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3621 
3622         glGenVertexArrays(1, &m_vertex_array);
3623         glEnable(GL_RASTERIZER_DISCARD);
3624 
3625         glUseProgram(m_program);
3626         glBindVertexArray(m_vertex_array);
3627 
3628         glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3629         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3630         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3631 
3632         glDrawArrays(GL_POINTS, 0, 1);
3633 
3634         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3635         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3636         GLubyte *out_data =
3637             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3638         if (!out_data)
3639             return ERROR;
3640 
3641         bool status = true;
3642         for (size_t i = 0; i < expected_data.size(); ++i)
3643         {
3644             if (expected_data[i] != out_data[i])
3645             {
3646                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3647                                                     << " is " << tcu::toHex(out_data[i]) << " should be "
3648                                                     << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3649                 status = false;
3650             }
3651         }
3652         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3653         if (!status)
3654             return ERROR;
3655         return NO_ERROR;
3656     }
3657 
Cleanup()3658     virtual long Cleanup()
3659     {
3660         glDisable(GL_RASTERIZER_DISCARD);
3661         glUseProgram(0);
3662         glDeleteProgram(m_program);
3663         glDeleteBuffers(2, m_buffer);
3664         glDeleteVertexArrays(1, &m_vertex_array);
3665         return NO_ERROR;
3666     }
3667 };
3668 
3669 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3670 {
3671     GLuint m_program;
3672     GLuint m_buffer[2];
3673 
3674     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data) = 0;
3675 
Setup()3676     virtual long Setup()
3677     {
3678         m_program = 0;
3679         memset(m_buffer, 0, sizeof(m_buffer));
3680         return NO_ERROR;
3681     }
3682 
Run()3683     virtual long Run()
3684     {
3685         std::vector<GLubyte> in_data;
3686         std::vector<GLubyte> expected_data;
3687 
3688         std::stringstream ss;
3689         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data, expected_data);
3690         m_program = CreateProgramCS(ss.str());
3691         glLinkProgram(m_program);
3692         if (!CheckProgram(m_program))
3693             return ERROR;
3694 
3695         glGenBuffers(2, m_buffer);
3696 
3697         /* output buffer */
3698         {
3699             std::vector<GLubyte> zero(expected_data.size());
3700             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3701             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3702         }
3703         // input buffer
3704         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3705         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3706 
3707         glUseProgram(m_program);
3708         glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3709         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3710         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3711         glDispatchCompute(1, 1, 1);
3712 
3713         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3714         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3715         GLubyte *out_data =
3716             (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3717         if (!out_data)
3718             return ERROR;
3719 
3720         bool status = true;
3721         for (size_t i = 0; i < expected_data.size(); ++i)
3722         {
3723             if (expected_data[i] != out_data[i])
3724             {
3725                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3726                                                     << " is " << tcu::toHex(out_data[i]) << " should be "
3727                                                     << tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3728                 status = false;
3729             }
3730         }
3731         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3732         if (!status)
3733             return ERROR;
3734         return NO_ERROR;
3735     }
3736 
Cleanup()3737     virtual long Cleanup()
3738     {
3739         glUseProgram(0);
3740         glDeleteProgram(m_program);
3741         glDeleteBuffers(2, m_buffer);
3742         return NO_ERROR;
3743     }
3744 };
3745 
3746 //-----------------------------------------------------------------------------
3747 // 1.10.1 BasicOperationsCase1
3748 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3749 const char *GetInputOp1(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3750 {
3751     /* input */
3752     {
3753         in_data.resize(16 * 9);
3754         int *ip   = reinterpret_cast<int *>(&in_data[0]);
3755         float *fp = reinterpret_cast<float *>(&in_data[0]);
3756         ip[0]     = 1;
3757         ip[1]     = 2;
3758         ip[2]     = 3;
3759         ip[3]     = 4; // data0
3760         fp[4]     = 1.0f;
3761         fp[5]     = 2.0f;
3762         fp[6]     = 3.0f;
3763         fp[7]     = 0.0f; // data1
3764         ip[8]     = 1;
3765         ip[9]     = 2;
3766         ip[10]    = 3;
3767         ip[11]    = 4; // data2
3768         ip[12]    = 1;
3769         ip[13]    = -2;
3770         ip[14]    = 3;
3771         ip[15]    = 4; // data3
3772         fp[16]    = 1.0f;
3773         fp[17]    = 2.0f;
3774         fp[18]    = 3.0f;
3775         fp[19]    = 4.0f; // data4
3776         fp[20]    = 1.0f;
3777         fp[21]    = 2.0f;
3778         fp[22]    = 3.0f;
3779         fp[23]    = 4.0f; // data5
3780         fp[24]    = 1.0f;
3781         fp[25]    = 2.0f;
3782         fp[26]    = 3.0f;
3783         fp[27]    = 4.0f; // data5
3784         fp[28]    = 1.0f;
3785         fp[29]    = 2.0f;
3786         fp[30]    = 3.0f;
3787         fp[31]    = 4.0f; // data5
3788         fp[32]    = 1.0f;
3789         fp[33]    = 0.0f;
3790         fp[34]    = 0.0f;
3791         fp[35]    = 4.0f; // data5
3792     }
3793     /* expected output */
3794     {
3795         out_data.resize(16 * 9);
3796         int *ip   = reinterpret_cast<int *>(&out_data[0]);
3797         float *fp = reinterpret_cast<float *>(&out_data[0]);
3798         ip[0]     = 4;
3799         ip[1]     = 3;
3800         ip[2]     = 2;
3801         ip[3]     = 1;
3802         fp[4]     = 3.0f;
3803         fp[5]     = 2.0f;
3804         fp[6]     = 1.0f;
3805         fp[7]     = 0.0f;
3806         ip[8]     = 4;
3807         ip[9]     = 1;
3808         ip[10]    = 0;
3809         ip[11]    = 3;
3810         ip[12]    = 10;
3811         ip[13]    = 4;
3812         ip[14]    = -2;
3813         ip[15]    = 20;
3814         fp[16]    = 50.0f;
3815         fp[17]    = 5.0f;
3816         fp[18]    = 2.0f;
3817         fp[19]    = 30.0f;
3818         fp[20]    = 4.0f;
3819         fp[21]    = 2.0f;
3820         fp[22]    = 3.0f;
3821         fp[23]    = 1.0f; // data5
3822         fp[24]    = 4.0f;
3823         fp[25]    = 3.0f;
3824         fp[26]    = 2.0f;
3825         fp[27]    = 1.0f; // data5
3826         fp[28]    = 2.0f;
3827         fp[29]    = 2.0f;
3828         fp[30]    = 2.0f;
3829         fp[31]    = 2.0f; // data5
3830         fp[32]    = 4.0f;
3831         fp[33]    = 0.0f;
3832         fp[34]    = 0.0f;
3833         fp[35]    = 1.0f; // data5
3834     }
3835 
3836     return NL "layout(std430, binding = 0) buffer Input {" NL "  ivec4 data0;" NL "  vec3 data1;" NL "  uvec4 data2;" NL
3837               "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_input;" NL
3838               "layout(std430, binding = 1) buffer Output {" NL "  ivec4 data0;" NL "  vec3 data1;" NL
3839               "  uvec4 data2;" NL "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_output;" NL
3840               "uniform vec3 g_value0;" NL "uniform int g_index1;" NL "void main() {" NL "  int index0 = 0;" NL
3841               "  g_output.data0.wzyx = g_input.data0;" NL "  g_output.data1 = g_input.data1.zyx;" NL
3842               "  g_output.data2.xwy = g_input.data2.wzx;" NL "  g_output.data3.xw = ivec2(10, 20);" NL
3843               "  g_output.data3.zy = g_input.data3.yw;" NL "  g_output.data4.wx = g_value0.xz;" // w == 10.0, x == 30.0
3844         NL "  g_output.data4.wx += g_value0.yy;"                                                // w == 30.0, x == 50.0
3845         NL "  g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;"                         // y == 5.0, z == 2.0
3846         NL "  g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
3847               "  g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
3848               "  g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
3849               "  g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
3850 }
3851 
3852 class BasicOperationsCase1VS : public BasicOperationsBaseVS
3853 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3854     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3855     {
3856         return GetInputOp1(in_data, out_data);
3857     }
3858 };
3859 
3860 class BasicOperationsCase1CS : public BasicOperationsBaseCS
3861 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3862     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3863     {
3864         return GetInputOp1(in_data, out_data);
3865     }
3866 };
3867 
3868 //-----------------------------------------------------------------------------
3869 // 1.10.2 BasicOperationsCase2
3870 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3871 const char *GetInputOp2(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3872 {
3873     /* input */
3874     {
3875         in_data.resize(16 * 8);
3876         float *fp = reinterpret_cast<float *>(&in_data[0]);
3877         fp[0]     = 1.0f;
3878         fp[1]     = 0.0f;
3879         fp[2]     = 0.0f;
3880         fp[3]     = 0.0f;
3881         fp[4]     = 0.0f;
3882         fp[5]     = 1.0f;
3883         fp[6]     = 0.0f;
3884         fp[7]     = 0.0f;
3885         fp[8]     = 0.0f;
3886         fp[9]     = 0.0f;
3887         fp[10]    = 1.0f;
3888         fp[11]    = 0.0f;
3889         fp[12]    = 0.0f;
3890         fp[13]    = 0.0f;
3891         fp[14]    = 0.0f;
3892         fp[15]    = 1.0f;
3893 
3894         fp[16] = 2.0f;
3895         fp[17] = 0.0f;
3896         fp[18] = 0.0f;
3897         fp[19] = 0.0f;
3898         fp[20] = 0.0f;
3899         fp[21] = 3.0f;
3900         fp[22] = 0.0f;
3901         fp[23] = 0.0f;
3902         fp[24] = 0.0f;
3903         fp[25] = 0.0f;
3904         fp[26] = 4.0f;
3905         fp[27] = 0.0f;
3906         fp[28] = 0.0f;
3907         fp[29] = 0.0f;
3908         fp[30] = 0.0f;
3909         fp[31] = 5.0f;
3910     }
3911     /* expected output */
3912     {
3913         out_data.resize(16 * 5);
3914         float *fp = reinterpret_cast<float *>(&out_data[0]);
3915         fp[0]     = 2.0f;
3916         fp[1]     = 0.0f;
3917         fp[2]     = 0.0f;
3918         fp[3]     = 0.0f;
3919         fp[4]     = 0.0f;
3920         fp[5]     = 3.0f;
3921         fp[6]     = 0.0f;
3922         fp[7]     = 0.0f;
3923         fp[8]     = 0.0f;
3924         fp[9]     = 0.0f;
3925         fp[10]    = 4.0f;
3926         fp[11]    = 0.0f;
3927         fp[12]    = 0.0f;
3928         fp[13]    = 0.0f;
3929         fp[14]    = 0.0f;
3930         fp[15]    = 5.0f;
3931 
3932         fp[16] = 0.0f;
3933         fp[17] = 1.0f;
3934         fp[18] = 4.0f;
3935         fp[19] = 0.0f;
3936     }
3937     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4 data0;" NL "  mat4 data1;" NL "} g_input;" NL
3938               "layout(std430, binding = 1) buffer Output {" NL "  mat4 data0;" NL "  vec4 data1;" NL "} g_output;" NL
3939               "uniform int g_index2;" NL "void main() {" NL
3940               "  g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
3941               "  g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
3942 }
3943 
3944 class BasicOperationsCase2VS : public BasicOperationsBaseVS
3945 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3947     {
3948         return GetInputOp2(in_data, out_data);
3949     }
3950 };
3951 
3952 class BasicOperationsCase2CS : public BasicOperationsBaseCS
3953 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3954     virtual const char *GetInput(std::vector<GLubyte> &in_data, std::vector<GLubyte> &out_data)
3955     {
3956         return GetInputOp2(in_data, out_data);
3957     }
3958 };
3959 
3960 //-----------------------------------------------------------------------------
3961 // 1.11.x BasicStdLayoutBase3
3962 //-----------------------------------------------------------------------------
3963 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
3964 {
3965     GLuint m_program;
3966     GLuint m_buffer[4];
3967     GLuint m_vertex_array;
3968 
3969     virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
3970 
Setup()3971     virtual long Setup()
3972     {
3973         m_program = 0;
3974         memset(m_buffer, 0, sizeof(m_buffer));
3975         m_vertex_array = 0;
3976         return NO_ERROR;
3977     }
3978 
Run()3979     virtual long Run()
3980     {
3981         if (!IsVSFSAvailable(4, 0))
3982             return NOT_SUPPORTED;
3983         std::vector<GLubyte> in_data[2];
3984         const char *glsl_vs       = GetInput(in_data);
3985         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
3986                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
3987 
3988         m_program = CreateProgram(glsl_vs, glsl_fs);
3989         glLinkProgram(m_program);
3990         if (!CheckProgram(m_program))
3991             return ERROR;
3992 
3993         glGenBuffers(4, m_buffer);
3994 
3995         // input buffers
3996         glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
3997         glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
3998 
3999         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4000         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4001 
4002         /* output buffer 0 */
4003         {
4004             std::vector<GLubyte> out_data(in_data[0].size());
4005             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4006             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4007         }
4008         /* output buffer 1 */
4009         {
4010             std::vector<GLubyte> out_data(in_data[1].size());
4011             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4012             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4013         }
4014 
4015         glGenVertexArrays(1, &m_vertex_array);
4016         glEnable(GL_RASTERIZER_DISCARD);
4017 
4018         glUseProgram(m_program);
4019         glBindVertexArray(m_vertex_array);
4020 
4021         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4022 
4023         glDrawArrays(GL_POINTS, 0, 1);
4024 
4025         bool status = true;
4026         for (int j = 0; j < 2; ++j)
4027         {
4028             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4029             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4030             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
4031                                                             GL_MAP_READ_BIT);
4032             if (!out_data)
4033                 return ERROR;
4034 
4035             for (size_t i = 0; i < in_data[j].size(); ++i)
4036             {
4037                 if (in_data[j][i] != out_data[i])
4038                 {
4039                     m_context.getTestContext().getLog()
4040                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4041                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4042                         << tcu::TestLog::EndMessage;
4043                     status = false;
4044                 }
4045             }
4046             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4047         }
4048         if (!status)
4049             return ERROR;
4050         return NO_ERROR;
4051     }
4052 
Cleanup()4053     virtual long Cleanup()
4054     {
4055         glDisable(GL_RASTERIZER_DISCARD);
4056         glUseProgram(0);
4057         glDeleteProgram(m_program);
4058         glDeleteBuffers(4, m_buffer);
4059         glDeleteVertexArrays(1, &m_vertex_array);
4060         return NO_ERROR;
4061     }
4062 };
4063 
4064 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4065 {
4066     GLuint m_program;
4067     GLuint m_buffer[4];
4068 
4069     virtual const char *GetInput(std::vector<GLubyte> in_data[2]) = 0;
4070 
Setup()4071     virtual long Setup()
4072     {
4073         m_program = 0;
4074         memset(m_buffer, 0, sizeof(m_buffer));
4075         return NO_ERROR;
4076     }
4077 
Run()4078     virtual long Run()
4079     {
4080         std::vector<GLubyte> in_data[2];
4081 
4082         std::stringstream ss;
4083         ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
4084         m_program = CreateProgramCS(ss.str());
4085         glLinkProgram(m_program);
4086         if (!CheckProgram(m_program))
4087             return ERROR;
4088 
4089         glGenBuffers(4, m_buffer);
4090 
4091         // input buffers
4092         glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4093         glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4094 
4095         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4096         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4097 
4098         /* output buffer 0 */
4099         {
4100             std::vector<GLubyte> out_data(in_data[0].size());
4101             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4102             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4103         }
4104         /* output buffer 1 */
4105         {
4106             std::vector<GLubyte> out_data(in_data[1].size());
4107             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4108             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4109         }
4110 
4111         glUseProgram(m_program);
4112         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4113         glDispatchCompute(1, 1, 1);
4114 
4115         bool status = true;
4116         for (int j = 0; j < 2; ++j)
4117         {
4118             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4119             glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4120             GLubyte *out_data = (GLubyte *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(),
4121                                                             GL_MAP_READ_BIT);
4122             if (!out_data)
4123                 return ERROR;
4124 
4125             for (size_t i = 0; i < in_data[j].size(); ++i)
4126             {
4127                 if (in_data[j][i] != out_data[i])
4128                 {
4129                     m_context.getTestContext().getLog()
4130                         << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4131                         << tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4132                         << tcu::TestLog::EndMessage;
4133                     status = false;
4134                 }
4135             }
4136             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4137         }
4138         if (!status)
4139             return ERROR;
4140         return NO_ERROR;
4141     }
4142 
Cleanup()4143     virtual long Cleanup()
4144     {
4145         glUseProgram(0);
4146         glDeleteProgram(m_program);
4147         glDeleteBuffers(4, m_buffer);
4148         return NO_ERROR;
4149     }
4150 };
4151 
4152 //-----------------------------------------------------------------------------
4153 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4154 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4155 const char *GetInputUBO1(std::vector<GLubyte> in_data[2])
4156 {
4157     /* UBO */
4158     {
4159         in_data[0].resize(12 * 4);
4160         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4161         fp[0]     = 1.0f;
4162         fp[1]     = 0.0f;
4163         fp[2]     = 0.0f;
4164         fp[3]     = 0.0f;
4165         fp[4]     = 2.0f;
4166         fp[5]     = 0.0f;
4167         fp[6]     = 0.0f;
4168         fp[7]     = 0.0f;
4169         fp[8]     = 3.0f;
4170         fp[9]     = 0.0f;
4171         fp[10]    = 0.0f;
4172         fp[11]    = 0.0f;
4173     }
4174     /* SSBO */
4175     {
4176         in_data[1].resize(3 * 4);
4177         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4178         fp[0]     = 1.0f;
4179         fp[1]     = 2.0f;
4180         fp[2]     = 3.0f;
4181     }
4182 
4183     return NL
4184         "layout(std140, binding = 0) uniform InputUBO {" NL "  float data0;" NL "  float data1[2];" NL
4185         "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL "  float data0;" NL
4186         "  float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4187         "  float data0;" NL "  float data1[2];" NL "} g_output_ubo;" NL
4188         "layout(std430, binding = 2) buffer OutputSSBO {" NL "  float data0;" NL "  float data1[2];" NL
4189         "} g_output_ssbo;" NL "void main() {" NL "  g_output_ubo.data0 = g_input_ubo.data0;" NL
4190         "  for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4191         "  g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4192         "  for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4193         "}";
4194 }
4195 
4196 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4197 {
GetInput(std::vector<GLubyte> in_data[2])4198     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4199     {
4200         return GetInputUBO1(in_data);
4201     }
4202 };
4203 
4204 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4205 {
GetInput(std::vector<GLubyte> in_data[2])4206     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4207     {
4208         return GetInputUBO1(in_data);
4209     }
4210 };
4211 
4212 //-----------------------------------------------------------------------------
4213 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4214 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4215 const char *GetInputUBO2(std::vector<GLubyte> in_data[2])
4216 {
4217     /* UBO */
4218     {
4219         in_data[0].resize(280 * 4);
4220         float *fp = reinterpret_cast<float *>(&in_data[0][0]);
4221         int *ip   = reinterpret_cast<int *>(&in_data[0][0]);
4222         fp[0]     = 1.0f;
4223         fp[1]     = 2.0f;
4224         fp[2]     = 3.0f;
4225         fp[3]     = 4.0f;
4226         fp[4]     = 5.0f;
4227         fp[5]     = 6.0f;
4228         fp[6]     = 7.0f;
4229         fp[8]     = 9.0f;
4230         fp[12]    = 10.0f;
4231         fp[16]    = 11.0f;
4232         fp[20]    = 12.0f;
4233         fp[24]    = 13.0f;
4234 
4235         ip[28] = 14;
4236         for (int i = 0; i < 20; ++i)
4237         {
4238             fp[32 + i * 4] = static_cast<float>(15 + i);
4239         }
4240         ip[112] = 140;
4241         for (int i = 0; i < 20; ++i)
4242         {
4243             fp[116 + i * 4] = static_cast<float>(150 + i);
4244         }
4245         ip[196] = 1400;
4246         for (int i = 0; i < 20; ++i)
4247         {
4248             fp[200 + i * 4] = static_cast<float>(1500 + i);
4249         }
4250     }
4251     /* SSBO */
4252     {
4253         in_data[1].resize(76 * 4);
4254         float *fp = reinterpret_cast<float *>(&in_data[1][0]);
4255         int *ip   = reinterpret_cast<int *>(&in_data[1][0]);
4256         fp[0]     = 1.0f;
4257         fp[1]     = 2.0f;
4258         fp[2]     = 3.0f;
4259         fp[3]     = 4.0f;
4260         fp[4]     = 5.0f;
4261         fp[5]     = 6.0f;
4262         fp[6]     = 7.0f;
4263         fp[7]     = 8.0f;
4264         fp[8]     = 9.0f;
4265         fp[9]     = 10.0f;
4266         fp[10]    = 11.0f;
4267         fp[11]    = 12.0f;
4268         fp[12]    = 13.0f;
4269         ip[13]    = 14;
4270         fp[14]    = 15.0f;
4271         fp[15]    = 16.0f;
4272         fp[16]    = 17.0f;
4273         fp[17]    = 18.0f;
4274         fp[18]    = 19.0f;
4275         fp[19]    = 20.0f;
4276         fp[20]    = 21.0f;
4277         fp[21]    = 22.0f;
4278         fp[22]    = 23.0f;
4279         fp[23]    = 24.0f;
4280         fp[24]    = 25.0f;
4281         fp[25]    = 26.0f;
4282         fp[26]    = 27.0f;
4283         fp[27]    = 28.0f;
4284         fp[28]    = 29.0f;
4285         fp[29]    = 30.0f;
4286         fp[30]    = 31.0f;
4287         fp[31]    = 32.0f;
4288         fp[32]    = 33.0f;
4289         fp[33]    = 34.0f;
4290         ip[34]    = 35;
4291         fp[35]    = 36.0f;
4292         fp[36]    = 37.0f;
4293         fp[37]    = 38.0f;
4294         fp[38]    = 39.0f;
4295         fp[39]    = 40.0f;
4296         fp[40]    = 41.0f;
4297         fp[41]    = 42.0f;
4298         fp[42]    = 43.0f;
4299         fp[43]    = 44.0f;
4300         fp[44]    = 45.0f;
4301         fp[45]    = 46.0f;
4302         fp[46]    = 47.0f;
4303         fp[47]    = 48.0f;
4304         fp[48]    = 49.0f;
4305         fp[49]    = 50.0f;
4306         fp[50]    = 51.0f;
4307         fp[51]    = 52.0f;
4308         fp[52]    = 53.0f;
4309         fp[53]    = 54.0f;
4310         fp[54]    = 55.0f;
4311         ip[55]    = 56;
4312         fp[56]    = 57.0f;
4313         fp[57]    = 58.0f;
4314         fp[58]    = 59.0f;
4315         fp[59]    = 60.0f;
4316         fp[60]    = 61.0f;
4317         fp[61]    = 62.0f;
4318         fp[62]    = 63.0f;
4319         fp[63]    = 64.0f;
4320         fp[64]    = 65.0f;
4321         fp[65]    = 66.0f;
4322         fp[66]    = 67.0f;
4323         fp[67]    = 68.0f;
4324         fp[68]    = 69.0f;
4325         fp[69]    = 70.0f;
4326         fp[70]    = 71.0f;
4327         fp[71]    = 72.0f;
4328         fp[72]    = 73.0f;
4329         fp[73]    = 74.0f;
4330         fp[74]    = 75.0f;
4331         fp[75]    = 76.0f;
4332     }
4333     return NL
4334         "struct MM {" NL "  float mm_a[5];" NL "};" NL "struct TT {" NL "  int tt_a;" NL "  MM  tt_b[4];" NL "};" NL
4335         "layout(std140, binding = 0) uniform InputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4336         "  float d[4];" NL "  TT    e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4337         "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_input_ssbo;" NL
4338         "layout(std140, binding = 1) buffer OutputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4339         "  float d[4];" NL "  TT    e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4340         "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_output_ssbo;" NL
4341         "uniform int g_index1;" NL "void main() {" NL "  int index0 = 0;" NL NL "  g_output_ubo.a = g_input_ubo.a;" NL
4342         "  g_output_ubo.b = g_input_ubo.b;" NL "  g_output_ubo.c = g_input_ubo.c;" NL
4343         "  for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4344         "    for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4345         "    g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4346         "    for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4347         "      g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4348         "      g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4349         "      g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4350         "      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 + "
4351         "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
4352         "    }" NL "  }" NL NL "  g_output_ssbo.a = g_input_ssbo.a;" NL "  g_output_ssbo.b = g_input_ssbo.b;" NL
4353         "  g_output_ssbo.c = g_input_ssbo.c;" NL
4354         "  for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4355         "  for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4356         "    g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4357         "    for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4358         "      g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4359         "      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
4360         "      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
4361         "      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 - "
4362         "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
4363         "  }" NL "}";
4364 }
4365 
4366 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4367 {
GetInput(std::vector<GLubyte> in_data[2])4368     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4369     {
4370         return GetInputUBO2(in_data);
4371     }
4372 };
4373 
4374 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4375 {
GetInput(std::vector<GLubyte> in_data[2])4376     virtual const char *GetInput(std::vector<GLubyte> in_data[2])
4377     {
4378         return GetInputUBO2(in_data);
4379     }
4380 };
4381 
4382 //-----------------------------------------------------------------------------
4383 // 1.12.x BasicMatrixOperationsBase
4384 //-----------------------------------------------------------------------------
4385 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4386 {
4387     GLuint m_program;
4388     GLuint m_buffer[2];
4389     GLuint m_vertex_array;
4390 
4391     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4392 
Equal(float a,float b)4393     static bool Equal(float a, float b)
4394     {
4395         return fabsf(a - b) < 0.001f;
4396     }
4397 
Setup()4398     virtual long Setup()
4399     {
4400         m_program = 0;
4401         memset(m_buffer, 0, sizeof(m_buffer));
4402         m_vertex_array = 0;
4403         return NO_ERROR;
4404     }
4405 
Run()4406     virtual long Run()
4407     {
4408         if (!IsVSFSAvailable(2, 0))
4409             return NOT_SUPPORTED;
4410         std::vector<float> in;
4411         std::vector<float> expected;
4412         const char *glsl_vs       = GetInput(in, expected);
4413         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
4414                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
4415 
4416         m_program = CreateProgram(glsl_vs, glsl_fs);
4417         glLinkProgram(m_program);
4418         if (!CheckProgram(m_program))
4419             return ERROR;
4420 
4421         glGenBuffers(2, m_buffer);
4422 
4423         /* output buffer */
4424         {
4425             std::vector<float> zero(expected.size());
4426             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4427             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4428                          GL_STATIC_DRAW);
4429         }
4430         // input buffer
4431         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4432         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4433 
4434         glGenVertexArrays(1, &m_vertex_array);
4435         glEnable(GL_RASTERIZER_DISCARD);
4436 
4437         glUseProgram(m_program);
4438         glBindVertexArray(m_vertex_array);
4439         glDrawArrays(GL_POINTS, 0, 1);
4440 
4441         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4442         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4443         float *out_data = (float *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4444                                                     (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4445         if (!out_data)
4446             return ERROR;
4447 
4448         bool status = true;
4449         for (size_t i = 0; i < expected.size(); ++i)
4450         {
4451             if (!Equal(expected[i], out_data[i]))
4452             {
4453                 m_context.getTestContext().getLog()
4454                     << tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4455                     << " should be " << expected[i] << tcu::TestLog::EndMessage;
4456                 status = false;
4457             }
4458         }
4459         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4460         if (!status)
4461             return ERROR;
4462         return NO_ERROR;
4463     }
4464 
Cleanup()4465     virtual long Cleanup()
4466     {
4467         glDisable(GL_RASTERIZER_DISCARD);
4468         glUseProgram(0);
4469         glDeleteProgram(m_program);
4470         glDeleteBuffers(2, m_buffer);
4471         glDeleteVertexArrays(1, &m_vertex_array);
4472         return NO_ERROR;
4473     }
4474 };
4475 
4476 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4477 {
4478     GLuint m_program;
4479     GLuint m_buffer[2];
4480 
4481     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected) = 0;
4482 
Equal(float a,float b)4483     static bool Equal(float a, float b)
4484     {
4485         return fabsf(a - b) < 0.001f;
4486     }
4487 
Setup()4488     virtual long Setup()
4489     {
4490         m_program = 0;
4491         memset(m_buffer, 0, sizeof(m_buffer));
4492         return NO_ERROR;
4493     }
4494 
Run()4495     virtual long Run()
4496     {
4497         std::vector<float> in;
4498         std::vector<float> expected;
4499         std::stringstream ss;
4500         ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4501         m_program = CreateProgramCS(ss.str());
4502         glLinkProgram(m_program);
4503         if (!CheckProgram(m_program))
4504             return ERROR;
4505 
4506         glGenBuffers(2, m_buffer);
4507 
4508         /* output buffer */
4509         {
4510             std::vector<float> zero(expected.size());
4511             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4512             glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4513                          GL_STATIC_DRAW);
4514         }
4515         // input buffer
4516         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4517         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4518 
4519         glUseProgram(m_program);
4520         glDispatchCompute(1, 1, 1);
4521 
4522         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4523         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4524         float *out_data = (float *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4525                                                     (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4526         if (!out_data)
4527             return ERROR;
4528 
4529         bool status = true;
4530         for (size_t i = 0; i < expected.size(); ++i)
4531         {
4532             if (!Equal(expected[i], out_data[i]))
4533             {
4534                 m_context.getTestContext().getLog()
4535                     << tcu::TestLog::Message << "Float at index  " << static_cast<int>(i) << " is " << out_data[i]
4536                     << " should be " << expected[i] << tcu::TestLog::EndMessage;
4537                 status = false;
4538             }
4539         }
4540         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4541         if (!status)
4542             return ERROR;
4543         return NO_ERROR;
4544     }
4545 
Cleanup()4546     virtual long Cleanup()
4547     {
4548         glUseProgram(0);
4549         glDeleteProgram(m_program);
4550         glDeleteBuffers(2, m_buffer);
4551         return NO_ERROR;
4552     }
4553 };
4554 
4555 //-----------------------------------------------------------------------------
4556 // 1.12.1 BasicMatrixOperationsCase1
4557 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4558 const char *GetInputM1(std::vector<float> &in, std::vector<float> &expected)
4559 {
4560     in.resize(8);
4561     in[0] = 1.0f;
4562     in[2] = 3.0f;
4563     in[1] = 2.0f;
4564     in[3] = 4.0f;
4565     in[4] = 1.0f;
4566     in[6] = 3.0f;
4567     in[5] = 2.0f;
4568     in[7] = 4.0f;
4569     expected.resize(4);
4570     expected[0] = 7.0f;
4571     expected[2] = 15.0f;
4572     expected[1] = 10.0f;
4573     expected[3] = 22.0f;
4574     return NL "layout(std430, binding = 0) buffer Input {" NL "  mat2 m0;" NL "  mat2 m1;" NL "} g_input;" NL
4575               "layout(std430, binding = 1) buffer Output {" NL "  mat2 m;" NL "} g_output;" NL
4576               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4577 }
4578 
4579 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4580 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4581     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4582     {
4583         return GetInputM1(in, expected);
4584     }
4585 };
4586 
4587 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4588 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4589     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4590     {
4591         return GetInputM1(in, expected);
4592     }
4593 };
4594 
4595 //-----------------------------------------------------------------------------
4596 // 1.12.2 BasicMatrixOperationsCase2
4597 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4598 const char *GetInputM2(std::vector<float> &in, std::vector<float> &expected)
4599 {
4600     in.resize(15);
4601     expected.resize(4);
4602     // mat3x2
4603     in[0] = 1.0f;
4604     in[2] = 3.0f;
4605     in[4] = 5.0f;
4606     in[1] = 2.0f;
4607     in[3] = 4.0f;
4608     in[5] = 6.0f;
4609     // mat2x3
4610     in[8]  = 1.0f;
4611     in[12] = 4.0f;
4612     in[9]  = 2.0f;
4613     in[13] = 5.0f;
4614     in[10] = 3.0f;
4615     in[14] = 6.0f;
4616     // mat2
4617     expected[0] = 22.0f;
4618     expected[2] = 49.0f;
4619     expected[1] = 28.0f;
4620     expected[3] = 64.0f;
4621     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4622               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4623               "  layout(column_major) mat2 m;" NL "} g_output;" NL
4624               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4625 }
4626 
4627 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4628 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4629     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4630     {
4631         return GetInputM2(in, expected);
4632     }
4633 };
4634 
4635 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4636 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4637     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4638     {
4639         return GetInputM2(in, expected);
4640     }
4641 };
4642 
4643 //-----------------------------------------------------------------------------
4644 // 1.12.3 BasicMatrixOperationsCase3
4645 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4646 const char *GetInputM3(std::vector<float> &in, std::vector<float> &expected)
4647 {
4648     in.resize(15);
4649     expected.resize(4);
4650     // row major mat3x2
4651     in[0] = 1.0f;
4652     in[1] = 3.0f;
4653     in[2] = 5.0f;
4654     in[4] = 2.0f;
4655     in[5] = 4.0f;
4656     in[6] = 6.0f;
4657     // row major mat2x3
4658     in[8]  = 1.0f;
4659     in[9]  = 4.0f;
4660     in[10] = 2.0f;
4661     in[11] = 5.0f;
4662     in[12] = 3.0f;
4663     in[13] = 6.0f;
4664     // row major mat2
4665     expected[0] = 22.0f;
4666     expected[1] = 49.0f;
4667     expected[2] = 28.0f;
4668     expected[3] = 64.0f;
4669 
4670     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4671               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4672               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4673 }
4674 
4675 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4676 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4677     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4678     {
4679         return GetInputM3(in, expected);
4680     }
4681 };
4682 
4683 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4684 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4685     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4686     {
4687         return GetInputM3(in, expected);
4688     }
4689 };
4690 
4691 //-----------------------------------------------------------------------------
4692 // 1.12.4 BasicMatrixOperationsCase4
4693 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4694 const char *GetInputM4(std::vector<float> &in, std::vector<float> &expected)
4695 {
4696     in.resize(15);
4697     expected.resize(4);
4698     // column major mat3x2
4699     in[0] = 1.0f;
4700     in[2] = 3.0f;
4701     in[4] = 5.0f;
4702     in[1] = 2.0f;
4703     in[3] = 4.0f;
4704     in[5] = 6.0f;
4705     // row major mat2x3
4706     in[8]  = 1.0f;
4707     in[9]  = 4.0f;
4708     in[10] = 2.0f;
4709     in[11] = 5.0f;
4710     in[12] = 3.0f;
4711     in[13] = 6.0f;
4712     // column major mat2
4713     expected[0] = 13.0f;
4714     expected[1] = 16.0f;
4715     expected[2] = 37.0f;
4716     expected[3] = 46.0f;
4717     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4718               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4719               "  layout(column_major) mat2 m;" NL "} g_output;" NL
4720               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4721 }
4722 
4723 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4724 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4725     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4726     {
4727         return GetInputM4(in, expected);
4728     }
4729 };
4730 
4731 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4732 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4733     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4734     {
4735         return GetInputM4(in, expected);
4736     }
4737 };
4738 
4739 //-----------------------------------------------------------------------------
4740 // 1.12.5 BasicMatrixOperationsCase5
4741 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4742 const char *GetInputM5(std::vector<float> &in, std::vector<float> &expected)
4743 {
4744     in.resize(15);
4745     expected.resize(4);
4746     // column major mat3x2
4747     in[0] = 1.0f;
4748     in[2] = 3.0f;
4749     in[4] = 5.0f;
4750     in[1] = 2.0f;
4751     in[3] = 4.0f;
4752     in[5] = 6.0f;
4753     // row major mat2x3
4754     in[8]  = 1.0f;
4755     in[9]  = 4.0f;
4756     in[10] = 2.0f;
4757     in[11] = 5.0f;
4758     in[12] = 3.0f;
4759     in[13] = 6.0f;
4760     // row major mat2
4761     expected[0] = 13.0f;
4762     expected[1] = 37.0f;
4763     expected[2] = 16.0f;
4764     expected[3] = 46.0f;
4765     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4766               "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4767               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4768 }
4769 
4770 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4771 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4772     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4773     {
4774         return GetInputM5(in, expected);
4775     }
4776 };
4777 
4778 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4779 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4780     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4781     {
4782         return GetInputM5(in, expected);
4783     }
4784 };
4785 
4786 //-----------------------------------------------------------------------------
4787 // 1.12.6 BasicMatrixOperationsCase6
4788 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4789 const char *GetInputM6(std::vector<float> &in, std::vector<float> &expected)
4790 {
4791     in.resize(20);
4792     expected.resize(4);
4793     // row major mat3x2
4794     in[0] = 1.0f;
4795     in[1] = 3.0f;
4796     in[2] = 5.0f;
4797     in[4] = 2.0f;
4798     in[5] = 4.0f;
4799     in[6] = 6.0f;
4800     // column major mat2x3
4801     in[8]  = 1.0f;
4802     in[12] = 4.0f;
4803     in[9]  = 2.0f;
4804     in[13] = 5.0f;
4805     in[10] = 3.0f;
4806     in[14] = 6.0f;
4807     // column major mat2
4808     expected[0] = 22.0f;
4809     expected[1] = 28.0f;
4810     expected[2] = 49.0f;
4811     expected[3] = 64.0f;
4812     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4813               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4814               "  layout(column_major) mat2 m;" NL "} g_output;" NL
4815               "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4816 }
4817 
4818 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
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 GetInputM6(in, expected);
4823     }
4824 };
4825 
4826 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
4827 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4828     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4829     {
4830         return GetInputM6(in, expected);
4831     }
4832 };
4833 
4834 //-----------------------------------------------------------------------------
4835 // 1.12.7 BasicMatrixOperationsCase7
4836 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)4837 const char *GetInputM7(std::vector<float> &in, std::vector<float> &expected)
4838 {
4839     in.resize(20);
4840     expected.resize(4);
4841     // row major mat3x2
4842     in[0] = 1.0f;
4843     in[1] = 3.0f;
4844     in[2] = 5.0f;
4845     in[4] = 2.0f;
4846     in[5] = 4.0f;
4847     in[6] = 6.0f;
4848     // column major mat2x3
4849     in[8]  = 1.0f;
4850     in[12] = 4.0f;
4851     in[9]  = 2.0f;
4852     in[13] = 5.0f;
4853     in[10] = 3.0f;
4854     in[14] = 6.0f;
4855     // row major mat2
4856     expected[0] = 22.0f;
4857     expected[1] = 49.0f;
4858     expected[2] = 28.0f;
4859     expected[3] = 64.0f;
4860     return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4861               "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4862               "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4863 }
4864 
4865 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
4866 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4867     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4868     {
4869         return GetInputM7(in, expected);
4870     }
4871 };
4872 
4873 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
4874 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4875     virtual const char *GetInput(std::vector<float> &in, std::vector<float> &expected)
4876     {
4877         return GetInputM7(in, expected);
4878     }
4879 };
4880 
4881 //-----------------------------------------------------------------------------
4882 // 2.1 AdvancedSwitchBuffers
4883 //-----------------------------------------------------------------------------
4884 class AdvancedSwitchBuffersVS : public ShaderStorageBufferObjectBase
4885 {
PassCriteria()4886     virtual std::string PassCriteria()
4887     {
4888         return NL "Everything works as expected.";
4889     }
4890 
4891     GLuint m_program;
4892     GLuint m_storage_buffer[5];
4893     GLuint m_vertex_array;
4894     GLuint m_fbo, m_rt;
4895 
Setup()4896     virtual long Setup()
4897     {
4898         m_program = 0;
4899         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
4900         m_vertex_array = 0;
4901         glGenFramebuffers(1, &m_fbo);
4902         glGenTextures(1, &m_rt);
4903         return NO_ERROR;
4904     }
4905 
Run()4906     virtual long Run()
4907     {
4908         if (!IsVSFSAvailable(1, 0))
4909             return NOT_SUPPORTED;
4910         const char *const glsl_vs = NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
4911                                        "layout(binding = 0, std430) buffer Input {" NL "  VertexData vertex[4];" NL
4912                                        "} g_vs_in;" NL "out vec3 StageData_color;" NL "void main() {" NL
4913                                        "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
4914                                        "  StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
4915         const char *const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
4916                                        "void main() {" NL "  g_fs_out = vec4(StageData_color, 1);" NL "}";
4917         m_program = CreateProgram(glsl_vs, glsl_fs);
4918         glLinkProgram(m_program);
4919         if (!CheckProgram(m_program))
4920             return ERROR;
4921 
4922         glGenBuffers(5, m_storage_buffer);
4923 
4924         /* left, bottom, red quad */
4925         {
4926             const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4927                                   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4928                                   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4929                                   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
4930             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
4931             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4932         }
4933         /* right, bottom, green quad */
4934         {
4935             const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4936                                   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4937                                   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4938                                   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
4939             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
4940             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4941         }
4942         /* left, top, blue quad */
4943         {
4944             const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4945                                   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4946                                   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4947                                   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
4948             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
4949             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4950         }
4951         /* right, top, yellow quad */
4952         {
4953             const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4954                                   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4955                                   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4956                                   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
4957             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
4958             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4959         }
4960 
4961         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
4962         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
4963 
4964         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
4965         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
4966         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
4967         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
4968         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
4969         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
4970                             sizeof(float) * 32);
4971         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
4972         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
4973                             sizeof(float) * 32);
4974 
4975         glBindTexture(GL_TEXTURE_2D, m_rt);
4976         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4977         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4978         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
4979         glBindTexture(GL_TEXTURE_2D, 0);
4980         glViewport(0, 0, 100, 100);
4981         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
4982         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
4983 
4984         glGenVertexArrays(1, &m_vertex_array);
4985 
4986         glUseProgram(m_program);
4987         glBindVertexArray(m_vertex_array);
4988 
4989         glClear(GL_COLOR_BUFFER_BIT);
4990         for (int i = 0; i < 4; ++i)
4991         {
4992             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
4993             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4994         }
4995         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
4996         {
4997             return ERROR;
4998         }
4999 
5000         glClear(GL_COLOR_BUFFER_BIT);
5001         for (int i = 0; i < 4; ++i)
5002         {
5003             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5004                               sizeof(float) * 32);
5005             glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5006         }
5007         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5008         {
5009             return ERROR;
5010         }
5011 
5012         return NO_ERROR;
5013     }
5014 
Cleanup()5015     virtual long Cleanup()
5016     {
5017         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5018         glUseProgram(0);
5019         glDeleteProgram(m_program);
5020         glDeleteBuffers(5, m_storage_buffer);
5021         glDeleteVertexArrays(1, &m_vertex_array);
5022         glDeleteFramebuffers(1, &m_fbo);
5023         glDeleteTextures(1, &m_rt);
5024         return NO_ERROR;
5025     }
5026 };
5027 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5028 {
5029     GLuint m_program;
5030     GLuint m_storage_buffer[6];
5031 
Setup()5032     virtual long Setup()
5033     {
5034         m_program = 0;
5035         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5036         return NO_ERROR;
5037     }
5038 
Run()5039     virtual long Run()
5040     {
5041         const char *const glsl_cs =
5042             NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL "  uint cookie[4];" NL
5043                "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL
5044                "void main() {" NL "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5045                "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5046                "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5047                "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5048                "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5049         m_program = CreateProgramCS(glsl_cs);
5050         glLinkProgram(m_program);
5051         if (!CheckProgram(m_program))
5052             return ERROR;
5053 
5054         glGenBuffers(6, m_storage_buffer);
5055 
5056         const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5057         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5058         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5059         const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5060         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5061         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5062         const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5063         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5064         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5065         const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5066         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5067         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5068 
5069         GLint alignment;
5070         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5071         GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5072         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5073         glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5074 
5075         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5076         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5077         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5078         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5079         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5080         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5081         glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5082         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5083 
5084         const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5085         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5086         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5087 
5088         glUseProgram(m_program);
5089         for (int i = 0; i < 4; ++i)
5090         {
5091             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5092             glDispatchCompute(1, 1, 1);
5093         }
5094         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5095         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5096         GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5097         if (!out_data)
5098             return ERROR;
5099         GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5100         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5101             out_data[3] != expected[3])
5102         {
5103             m_context.getTestContext().getLog()
5104                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5105                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5106                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5107                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5108             return ERROR;
5109         }
5110         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5111         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5112 
5113         for (int i = 0; i < 4; ++i)
5114         {
5115             glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5116             glDispatchCompute(1, 1, 1);
5117         }
5118         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5119         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5120         out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5121         if (!out_data)
5122             return ERROR;
5123         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5124             out_data[3] != expected[3])
5125         {
5126             m_context.getTestContext().getLog()
5127                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5128                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5129                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5130                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5131             return ERROR;
5132         }
5133 
5134         return NO_ERROR;
5135     }
5136 
Cleanup()5137     virtual long Cleanup()
5138     {
5139         glUseProgram(0);
5140         glDeleteProgram(m_program);
5141         glDeleteBuffers(6, m_storage_buffer);
5142         return NO_ERROR;
5143     }
5144 };
5145 //-----------------------------------------------------------------------------
5146 // 2.2 AdvancedSwitchPrograms
5147 //-----------------------------------------------------------------------------
5148 class AdvancedSwitchProgramsVS : public ShaderStorageBufferObjectBase
5149 {
5150     GLuint m_program[4];
5151     GLuint m_storage_buffer[4];
5152     GLuint m_vertex_array;
5153     GLuint m_fbo, m_rt;
5154 
GenSource(int binding)5155     std::string GenSource(int binding)
5156     {
5157         std::stringstream ss;
5158         ss << NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL "layout(binding = "
5159            << binding
5160            << ", std430) buffer Input {" NL "  VertexData vertex[4];" NL "} g_vs_in;" NL "out vec3 StageData_color;" NL
5161               "void main() {" NL "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5162               "  StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5163         return ss.str();
5164     }
5165 
Setup()5166     virtual long Setup()
5167     {
5168         memset(m_program, 0, sizeof(m_program));
5169         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5170         m_vertex_array = 0;
5171         glGenFramebuffers(1, &m_fbo);
5172         glGenTextures(1, &m_rt);
5173         return NO_ERROR;
5174     }
5175 
Run()5176     virtual long Run()
5177     {
5178         if (!IsVSFSAvailable(1, 0))
5179             return NOT_SUPPORTED;
5180         const char *const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5181                                        "void main() {" NL "  g_fs_out = vec4(StageData_color, 1);" NL "}";
5182         for (int i = 0; i < 4; ++i)
5183         {
5184             m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5185             glLinkProgram(m_program[i]);
5186             if (!CheckProgram(m_program[i]))
5187                 return ERROR;
5188         }
5189 
5190         glGenBuffers(4, m_storage_buffer);
5191 
5192         /* left, bottom, red quad */
5193         {
5194             const float data[] = {-0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5195                                   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5196                                   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5197                                   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f};
5198             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5199             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5200         }
5201         /* right, bottom, green quad */
5202         {
5203             const float data[] = {-0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5204                                   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5205                                   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5206                                   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
5207             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5208             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5209         }
5210         /* left, top, blue quad */
5211         {
5212             const float data[] = {-0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5213                                   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5214                                   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5215                                   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f};
5216             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5217             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5218         }
5219         /* right, top, yellow quad */
5220         {
5221             const float data[] = {-0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5222                                   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5223                                   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5224                                   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f};
5225             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5226             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5227         }
5228 
5229         glBindTexture(GL_TEXTURE_2D, m_rt);
5230         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5231         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5232         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5233         glBindTexture(GL_TEXTURE_2D, 0);
5234         glViewport(0, 0, 100, 100);
5235         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5236         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5237 
5238         glGenVertexArrays(1, &m_vertex_array);
5239         glBindVertexArray(m_vertex_array);
5240 
5241         glClear(GL_COLOR_BUFFER_BIT);
5242         for (int i = 0; i < 4; ++i)
5243         {
5244             glUseProgram(m_program[i]);
5245             glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5246         }
5247         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5248         {
5249             return ERROR;
5250         }
5251 
5252         return NO_ERROR;
5253     }
5254 
Cleanup()5255     virtual long Cleanup()
5256     {
5257         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5258         glUseProgram(0);
5259         for (int i = 0; i < 4; ++i)
5260             glDeleteProgram(m_program[i]);
5261         glDeleteBuffers(4, m_storage_buffer);
5262         glDeleteVertexArrays(1, &m_vertex_array);
5263         glDeleteFramebuffers(1, &m_fbo);
5264         glDeleteTextures(1, &m_rt);
5265         return NO_ERROR;
5266     }
5267 };
5268 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5269 {
5270     GLuint m_program[4];
5271     GLuint m_storage_buffer[5];
5272 
Setup()5273     virtual long Setup()
5274     {
5275         memset(m_program, 0, sizeof(m_program));
5276         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5277         return NO_ERROR;
5278     }
5279 
GenSource(int binding)5280     std::string GenSource(int binding)
5281     {
5282         std::stringstream ss;
5283         ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5284            << ", std430) buffer Input {" NL "  uint cookie[4];" NL "} g_in;" NL
5285               "layout(binding = 0, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL "void main() {" NL
5286               "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5287               "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5288               "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5289               "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5290               "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5291         return ss.str();
5292     }
5293 
Run()5294     virtual long Run()
5295     {
5296         for (int i = 0; i < 4; ++i)
5297         {
5298             m_program[i] = CreateProgramCS(GenSource(i + 1));
5299             glLinkProgram(m_program[i]);
5300             if (!CheckProgram(m_program[i]))
5301                 return ERROR;
5302         }
5303 
5304         glGenBuffers(5, m_storage_buffer);
5305 
5306         const GLubyte data0[] = {0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22};
5307         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5308         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5309         const GLubyte data1[] = {0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0};
5310         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5311         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5312         const GLubyte data2[] = {0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0};
5313         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5314         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5315         const GLubyte data3[] = {0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0};
5316         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5317         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5318 
5319         const GLubyte data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5320         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5321         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5322 
5323         for (int i = 0; i < 4; ++i)
5324         {
5325             glUseProgram(m_program[i]);
5326             glDispatchCompute(1, 1, 1);
5327         }
5328         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5329         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5330         GLuint *out_data = (GLuint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5331         if (!out_data)
5332             return ERROR;
5333         GLuint expected[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
5334         if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5335             out_data[3] != expected[3])
5336         {
5337             m_context.getTestContext().getLog()
5338                 << tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5339                 << ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5340                 << ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5341                 << tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5342             return ERROR;
5343         }
5344         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5345 
5346         return NO_ERROR;
5347     }
5348 
Cleanup()5349     virtual long Cleanup()
5350     {
5351         glUseProgram(0);
5352         for (int i = 0; i < 4; ++i)
5353             glDeleteProgram(m_program[i]);
5354         glDeleteBuffers(5, m_storage_buffer);
5355         return NO_ERROR;
5356     }
5357 };
5358 
5359 //-----------------------------------------------------------------------------
5360 // 2.3.1 AdvancedWriteFragment
5361 //-----------------------------------------------------------------------------
5362 class AdvancedWriteFragmentFS : public ShaderStorageBufferObjectBase
5363 {
5364     GLuint m_program[2];
5365     GLuint m_storage_buffer;
5366     GLuint m_counter_buffer;
5367     GLuint m_attribless_vertex_array;
5368     GLuint m_draw_vertex_array;
5369     GLuint m_fbo, m_rt;
5370 
Setup()5371     virtual long Setup()
5372     {
5373         memset(m_program, 0, sizeof(m_program));
5374         m_storage_buffer          = 0;
5375         m_counter_buffer          = 0;
5376         m_attribless_vertex_array = 0;
5377         m_draw_vertex_array       = 0;
5378         glGenFramebuffers(1, &m_fbo);
5379         glGenTextures(1, &m_rt);
5380         return NO_ERROR;
5381     }
5382 
Run()5383     virtual long Run()
5384     {
5385         if (!IsVSFSAvailable(0, 1))
5386             return NOT_SUPPORTED;
5387         const char *const glsl_vs0 =
5388             NL "out vec2 position;" NL "out vec3 color;" NL
5389                "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
5390                "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
5391                "vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5392                "void main() {" NL "  vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5393                "  gl_Position = vec4(pos, 0, 1);" NL "  position = pos;" NL "  color = g_color[gl_InstanceID];" NL "}";
5394         const char *const glsl_fs0 =
5395             NL "in vec2 position;" NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5396                "struct FragmentData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5397                "layout(std430, binding = 3) buffer Output {" NL "  FragmentData g_fragment[6400];" NL "};" NL
5398                "uniform uint g_max_fragment_count;" NL
5399                "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5400                "  uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5401                "  if (fragment_number < g_max_fragment_count) {" NL
5402                "    g_fragment[fragment_number].position = position;" NL
5403                "    g_fragment[fragment_number].color = color;" NL "  }" NL "  g_fs_out = vec4(color, 1);" NL "}";
5404         m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5405         glLinkProgram(m_program[0]);
5406         if (!CheckProgram(m_program[0]))
5407             return ERROR;
5408 
5409         const char *const glsl_vs1 =
5410             NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5411                "out vec3 color;" NL "void main() {" NL "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5412                "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "  color = g_in_color.rgb;" NL "}";
5413         const char *const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5414                                         "void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5415         m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5416         glLinkProgram(m_program[1]);
5417         if (!CheckProgram(m_program[1]))
5418             return ERROR;
5419 
5420         // The first pass renders four squares on-screen, and writes a
5421         // record to the SSBO for each fragment processed.  The rectangles
5422         // will be 40x40 when using a 100x100 viewport, so we expect 1600
5423         // pixels per rectangle or 6400 pixels total.  Size the SSBO
5424         // accordingly, and render the second pass (sourcing the SSBO as a
5425         // vertex buffer) with an identical number of points.  If we have
5426         // a larger buffer and draw more points on the second pass, those
5427         // may overwrite "real" points using garbage position/color.
5428         int expectedPixels = 6400;
5429 
5430         glGenBuffers(1, &m_storage_buffer);
5431         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5432         glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5433 
5434         glGenBuffers(1, &m_counter_buffer);
5435         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5436         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5437         uvec4 zero(0);
5438         glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5439 
5440         glBindTexture(GL_TEXTURE_2D, m_rt);
5441         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5442         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5443         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5444         glBindTexture(GL_TEXTURE_2D, 0);
5445         glViewport(0, 0, 100, 100);
5446         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5447         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5448 
5449         glGenVertexArrays(1, &m_attribless_vertex_array);
5450 
5451         glGenVertexArrays(1, &m_draw_vertex_array);
5452         glBindVertexArray(m_draw_vertex_array);
5453         glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5454         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5455         glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
5456         glBindBuffer(GL_ARRAY_BUFFER, 0);
5457         glEnableVertexAttribArray(0);
5458         glEnableVertexAttribArray(1);
5459         glBindVertexArray(0);
5460 
5461         glClear(GL_COLOR_BUFFER_BIT);
5462         glUseProgram(m_program[0]);
5463         glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5464         glBindVertexArray(m_attribless_vertex_array);
5465         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5466         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5467         {
5468             return ERROR;
5469         }
5470 
5471         glClear(GL_COLOR_BUFFER_BIT);
5472         glUseProgram(m_program[1]);
5473         glBindVertexArray(m_draw_vertex_array);
5474         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5475         glDrawArrays(GL_POINTS, 0, expectedPixels);
5476         int bad_pixels;
5477         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5478             bad_pixels > 2)
5479         {
5480             return ERROR;
5481         }
5482 
5483         return NO_ERROR;
5484     }
5485 
Cleanup()5486     virtual long Cleanup()
5487     {
5488         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5489         glUseProgram(0);
5490         for (int i = 0; i < 2; ++i)
5491             glDeleteProgram(m_program[i]);
5492         glDeleteBuffers(1, &m_storage_buffer);
5493         glDeleteBuffers(1, &m_counter_buffer);
5494         glDeleteVertexArrays(1, &m_attribless_vertex_array);
5495         glDeleteVertexArrays(1, &m_draw_vertex_array);
5496         glDeleteFramebuffers(1, &m_fbo);
5497         glDeleteTextures(1, &m_rt);
5498         return NO_ERROR;
5499     }
5500 };
5501 
5502 class AdvancedWriteFragmentCS : public ShaderStorageBufferObjectBase
5503 {
5504     GLuint m_program[2];
5505     GLuint m_storage_buffer;
5506     GLuint m_counter_buffer;
5507     GLuint m_draw_vertex_array;
5508     GLuint m_fbo, m_rt;
5509 
Setup()5510     virtual long Setup()
5511     {
5512         memset(m_program, 0, sizeof(m_program));
5513         m_storage_buffer    = 0;
5514         m_counter_buffer    = 0;
5515         m_draw_vertex_array = 0;
5516         glGenFramebuffers(1, &m_fbo);
5517         glGenTextures(1, &m_rt);
5518         return NO_ERROR;
5519     }
5520 
Run()5521     virtual long Run()
5522     {
5523         const char *const glsl_cs = NL
5524             "layout(local_size_x = 10, local_size_y = 10) in;" NL "uniform uint g_max_point_count;" NL
5525             "uniform uint g_brick;" NL
5526             "vec3 g_color[5] = vec3[5](vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 0));" NL
5527             "struct PointData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5528             "layout(std430, binding = 3) buffer Output {" NL "  PointData g_point[];" NL "};" NL
5529             "layout(binding = 0, offset = 0) uniform atomic_uint g_point_counter;" NL "void main() {" NL
5530             "  uint g_offset[4] = uint[4](g_brick, 9u*g_brick, 11u*g_brick, 19u*g_brick);" NL
5531             "  uint point_number = atomicCounterIncrement(g_point_counter);" NL
5532             "  uint giidx = gl_GlobalInvocationID.x;" NL "  uint giidy = gl_GlobalInvocationID.y;" NL
5533             "  g_point[point_number].position = vec2(gl_GlobalInvocationID.xy * 2u) / 100.0 - 1.0;" NL
5534             "  g_point[point_number].color = g_color[4];" NL "  if (point_number < g_max_point_count) {" NL
5535             "    if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5536             "      g_point[point_number].color = g_color[0];" NL "    }" NL
5537             "    if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5538             "      g_point[point_number].color = g_color[1];" NL "    }" NL
5539             "    if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5540             "      g_point[point_number].color = g_color[2];" NL "    }" NL
5541             "    if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5542             "      g_point[point_number].color = g_color[3];" NL "    }" NL "  }" NL "}";
5543         m_program[0] = CreateProgramCS(glsl_cs);
5544         glLinkProgram(m_program[0]);
5545         if (!CheckProgram(m_program[0]))
5546             return ERROR;
5547 
5548         const char *const glsl_vs1 =
5549             NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5550                "out vec3 color;" NL "void main() {" NL "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5551                "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "  color = g_in_color.rgb;" NL "}";
5552         const char *const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5553                                         "void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5554         m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5555         glLinkProgram(m_program[1]);
5556         if (!CheckProgram(m_program[1]))
5557             return ERROR;
5558 
5559         glGenBuffers(1, &m_storage_buffer);
5560         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5561         glBufferData(GL_SHADER_STORAGE_BUFFER, 100 * 100 * 32, NULL, GL_DYNAMIC_DRAW);
5562 
5563         glGenBuffers(1, &m_counter_buffer);
5564         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
5565         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5566         uvec4 zero(0);
5567         glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5568 
5569         glGenVertexArrays(1, &m_draw_vertex_array);
5570         glBindVertexArray(m_draw_vertex_array);
5571         glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5572         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5573         glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
5574         glBindBuffer(GL_ARRAY_BUFFER, 0);
5575         glEnableVertexAttribArray(0);
5576         glEnableVertexAttribArray(1);
5577         glBindVertexArray(0);
5578 
5579         glUseProgram(m_program[0]);
5580         glUniform1ui(glGetUniformLocation(m_program[0], "g_max_point_count"), 100 * 100);
5581         glUniform1ui(glGetUniformLocation(m_program[0], "g_brick"), 5);
5582         glDispatchCompute(10, 10, 1);
5583 
5584         glBindTexture(GL_TEXTURE_2D, m_rt);
5585         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5586         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5587         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5588         glBindTexture(GL_TEXTURE_2D, 0);
5589         glViewport(0, 0, 100, 100);
5590         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5591         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5592 
5593         glClear(GL_COLOR_BUFFER_BIT);
5594         glUseProgram(m_program[1]);
5595         glBindVertexArray(m_draw_vertex_array);
5596         glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5597         glDrawArrays(GL_POINTS, 0, 100 * 100);
5598         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5599         {
5600             return ERROR;
5601         }
5602 
5603         return NO_ERROR;
5604     }
5605 
Cleanup()5606     virtual long Cleanup()
5607     {
5608         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5609         glUseProgram(0);
5610         for (int i = 0; i < 2; ++i)
5611             glDeleteProgram(m_program[i]);
5612         glDeleteBuffers(1, &m_storage_buffer);
5613         glDeleteBuffers(1, &m_counter_buffer);
5614         glDeleteVertexArrays(1, &m_draw_vertex_array);
5615         glDeleteFramebuffers(1, &m_fbo);
5616         glDeleteTextures(1, &m_rt);
5617         return NO_ERROR;
5618     }
5619 };
5620 
5621 //-----------------------------------------------------------------------------
5622 // 2.4.1 AdvancedIndirectAddressingCase1
5623 //-----------------------------------------------------------------------------
5624 class AdvancedIndirectAddressingCase1VS : public ShaderStorageBufferObjectBase
5625 {
5626     GLuint m_program;
5627     GLuint m_storage_buffer[4];
5628     GLuint m_vertex_array;
5629     GLuint m_vertex_buffer;
5630     GLuint m_fbo, m_rt;
5631 
Setup()5632     virtual long Setup()
5633     {
5634         m_program = 0;
5635         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5636         m_vertex_array  = 0;
5637         m_vertex_buffer = 0;
5638         glGenFramebuffers(1, &m_fbo);
5639         glGenTextures(1, &m_rt);
5640         return NO_ERROR;
5641     }
5642 
Run()5643     virtual long Run()
5644     {
5645         if (!IsVSFSAvailable(4, 0))
5646             return NOT_SUPPORTED;
5647         const char *const glsl_vs =
5648             NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
5649                "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
5650                "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
5651                "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
5652                "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
5653                "out vec3 color;" NL "void main() {" NL "  uint mid = g_material_id[gl_InstanceID];" NL
5654                "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_InstanceID];" NL
5655                "  vec2 t = g_transform.translation[tid];" NL "  gl_Position = vec4(g_in_position + t, 0, 1);" NL
5656                "  color = m.color;" NL "}";
5657         const char *const glsl_fs = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5658                                        "void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5659         m_program = CreateProgram(glsl_vs, glsl_fs);
5660         glLinkProgram(m_program);
5661         if (!CheckProgram(m_program))
5662             return ERROR;
5663 
5664         glGenBuffers(4, m_storage_buffer);
5665 
5666         /* material buffer */
5667         {
5668             const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5669                                   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
5670             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5671             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5672         }
5673         /* material id buffer */
5674         {
5675             const unsigned int data[] = {2, 3, 0, 2};
5676             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5677             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5678         }
5679         /* transform buffer */
5680         {
5681             const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
5682             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5683             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5684         }
5685         /* transform id buffer */
5686         {
5687             const unsigned int data[] = {3, 1, 0, 2};
5688             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5689             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5690         }
5691 
5692         /* vertex buffer */
5693         {
5694             const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
5695             glGenBuffers(1, &m_vertex_buffer);
5696             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5697             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5698             glBindBuffer(GL_ARRAY_BUFFER, 0);
5699         }
5700 
5701         glBindTexture(GL_TEXTURE_2D, m_rt);
5702         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5703         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5704         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5705         glBindTexture(GL_TEXTURE_2D, 0);
5706         glViewport(0, 0, 100, 100);
5707         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5708         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5709 
5710         glGenVertexArrays(1, &m_vertex_array);
5711         glBindVertexArray(m_vertex_array);
5712         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5713         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5714         glBindBuffer(GL_ARRAY_BUFFER, 0);
5715         glEnableVertexAttribArray(0);
5716         glBindVertexArray(0);
5717 
5718         glClear(GL_COLOR_BUFFER_BIT);
5719         glUseProgram(m_program);
5720         glBindVertexArray(m_vertex_array);
5721         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5722         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
5723         {
5724             return ERROR;
5725         }
5726 
5727         /* update material id buffer with BufferSubData */
5728         {
5729             const unsigned int data[] = {3, 2, 1, 0};
5730             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5731             glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5732         }
5733 
5734         /* update transform id buffer with BufferData */
5735         {
5736             const unsigned int data[] = {0, 1, 2, 3};
5737             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5738             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5739         }
5740 
5741         glClear(GL_COLOR_BUFFER_BIT);
5742         glUseProgram(m_program);
5743         glBindVertexArray(m_vertex_array);
5744         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5745         if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
5746         {
5747             return ERROR;
5748         }
5749 
5750         return NO_ERROR;
5751     }
5752 
Cleanup()5753     virtual long Cleanup()
5754     {
5755         glViewport(0, 0, getWindowWidth(), getWindowHeight());
5756         glUseProgram(0);
5757         glDeleteProgram(m_program);
5758         glDeleteBuffers(4, m_storage_buffer);
5759         glDeleteBuffers(1, &m_vertex_buffer);
5760         glDeleteVertexArrays(1, &m_vertex_array);
5761         glDeleteFramebuffers(1, &m_fbo);
5762         glDeleteTextures(1, &m_rt);
5763         return NO_ERROR;
5764     }
5765 };
5766 
5767 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
5768 {
5769     GLuint m_program;
5770     GLuint m_storage_buffer[5];
5771 
Setup()5772     virtual long Setup()
5773     {
5774         m_program = 0;
5775         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5776         return NO_ERROR;
5777     }
5778 
Run()5779     virtual long Run()
5780     {
5781         bool status = true;
5782         const char *const glsl_cs =
5783             NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
5784                "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
5785                "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
5786                "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
5787                "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
5788                "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[16];" NL "  vec2 pos[16];" NL
5789                "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
5790                "vec2(0.4f, 0.4f));" NL "void main() {" NL "  uint mid = g_material_id[gl_WorkGroupID.x];" NL
5791                "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_WorkGroupID.x];" NL
5792                "  vec2 t = g_transform.translation[tid];" NL
5793                "  pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
5794                "    = g_in_position[gl_LocalInvocationIndex] + t;" NL "  color[gl_LocalInvocationIndex + "
5795                "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
5796                "gl_WorkGroupSize.y] = m.color;" NL "}";
5797         m_program = CreateProgramCS(glsl_cs);
5798         glLinkProgram(m_program);
5799         if (!CheckProgram(m_program))
5800             return ERROR;
5801 
5802         glGenBuffers(5, m_storage_buffer);
5803 
5804         /* material buffer */
5805         {
5806             const float data[] = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5807                                   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
5808             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5809             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5810         }
5811         /* material id buffer */
5812         {
5813             const unsigned int data[] = {2, 3, 0, 2};
5814             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5815             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5816         }
5817         /* transform buffer */
5818         {
5819             const float data[] = {-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f};
5820             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5821             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5822         }
5823         /* transform id buffer */
5824         {
5825             const unsigned int data[] = {3, 1, 0, 2};
5826             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5827             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5828         }
5829 
5830         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5831         glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
5832 
5833         glUseProgram(m_program);
5834         glDispatchCompute(4, 1, 1);
5835         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5836         GLfloat *out_data =
5837             (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5838         if (!out_data)
5839             return ERROR;
5840 
5841         GLfloat expected[16 * 4 + 16 * 2] = {
5842             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,
5843             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,
5844             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,
5845             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,
5846             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,
5847             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,
5848             -0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f,  -0.1f, 0.1f,  -0.9f, 0.9f,  -0.1f, 0.9f};
5849         for (int i = 0; i < 16; ++i)
5850         {
5851             if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
5852                 out_data[i * 4 + 2] != expected[i * 4 + 2])
5853             {
5854                 m_context.getTestContext().getLog()
5855                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
5856                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
5857                     << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5858                 status = false;
5859             }
5860         }
5861         for (int i = 32; i < 32 + 16; ++i)
5862         {
5863             if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
5864                 fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
5865             {
5866                 m_context.getTestContext().getLog()
5867                     << tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
5868                     << ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1] << ", "
5869                     << tcu::TestLog::EndMessage;
5870                 status = false;
5871             }
5872         }
5873         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5874 
5875         /* update material id buffer with BufferSubData */
5876         {
5877             const unsigned int data[] = {3, 2, 1, 0};
5878             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5879             glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5880         }
5881 
5882         /* update transform id buffer with BufferData */
5883         {
5884             const unsigned int data[] = {0, 1, 2, 3};
5885             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5886             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5887         }
5888 
5889         glUseProgram(m_program);
5890         glDispatchCompute(4, 1, 1);
5891         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5892         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5893         GLfloat *out_data2 =
5894             (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5895         if (!out_data2)
5896             return ERROR;
5897 
5898         GLfloat expected2[16 * 4 + 16 * 2] = {
5899             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,
5900             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,
5901             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,
5902             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,
5903             -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,
5904             -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};
5905         for (int i = 0; i < 16; ++i)
5906         {
5907             if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
5908                 out_data2[i * 4 + 2] != expected2[i * 4 + 2])
5909             {
5910                 m_context.getTestContext().getLog()
5911                     << tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
5912                     << ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
5913                     << expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5914                 status = false;
5915             }
5916         }
5917         for (int i = 32; i < 32 + 16; ++i)
5918         {
5919             if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
5920                 fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
5921             {
5922                 m_context.getTestContext().getLog()
5923                     << tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
5924                     << ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1] << ", "
5925                     << tcu::TestLog::EndMessage;
5926                 status = false;
5927             }
5928         }
5929 
5930         if (status)
5931             return NO_ERROR;
5932         else
5933             return ERROR;
5934     }
5935 
Cleanup()5936     virtual long Cleanup()
5937     {
5938         glUseProgram(0);
5939         glDeleteProgram(m_program);
5940         glDeleteBuffers(5, m_storage_buffer);
5941         return NO_ERROR;
5942     }
5943 };
5944 //-----------------------------------------------------------------------------
5945 // 2.4.2 AdvancedIndirectAddressingCase2
5946 //-----------------------------------------------------------------------------
5947 class AdvancedIndirectAddressingCase2VSFS : public ShaderStorageBufferObjectBase
5948 {
5949     GLuint m_program;
5950     GLuint m_storage_buffer[8];
5951     GLuint m_vertex_array;
5952     GLuint m_vertex_buffer;
5953     GLuint m_fbo, m_rt;
5954 
Setup()5955     virtual long Setup()
5956     {
5957         m_program = 0;
5958         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5959         m_vertex_array  = 0;
5960         m_vertex_buffer = 0;
5961         glGenFramebuffers(1, &m_fbo);
5962         glGenTextures(1, &m_rt);
5963         return NO_ERROR;
5964     }
5965 
Run()5966     virtual long Run()
5967     {
5968         if (!IsVSFSAvailable(4, 4))
5969             return NOT_SUPPORTED;
5970         GLint blocksC;
5971         glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
5972         if (blocksC < 8)
5973             return NOT_SUPPORTED;
5974         const char *const glsl_vs =
5975             NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
5976                "  vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id;" NL "void main() {" NL
5977                "  vec2 translation = vec2(0);" NL "  switch (g_transform_id) {" NL "  case 0u:" NL
5978                "    translation = g_transform[0].translation;" NL "    break;" NL "  case 1u:" NL
5979                "    translation = g_transform[1].translation;" NL "    break;" NL "  case 2u:" NL
5980                "    translation = g_transform[2].translation;" NL "    break;" NL "  case 3u:" NL
5981                "    translation = g_transform[3].translation;" NL "    break;" NL "  }" NL
5982                "  gl_Position = vec4(g_in_position + translation, 0, 1);" NL "}";
5983         const char *const glsl_fs = NL
5984             "layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
5985             "  vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id;" NL "void main() {" NL
5986             "  vec3 color = vec3(0);" NL "  switch (g_material_id) {" NL "  case 0:" NL
5987             "    color = g_material[0].color;" NL "    break;" NL "  case 1:" NL "    color = g_material[1].color;" NL
5988             "    break;" NL "  case 2:" NL "    color = g_material[2].color;" NL "    break;" NL "  case 3:" NL
5989             "    color = g_material[3].color;" NL "    break;" NL "  }" NL "  g_fs_out = vec4(color, 1);" NL "}";
5990         m_program = CreateProgram(glsl_vs, glsl_fs);
5991         glLinkProgram(m_program);
5992         if (!CheckProgram(m_program))
5993             return ERROR;
5994 
5995         glGenBuffers(8, m_storage_buffer);
5996 
5997         /* transform buffers */
5998         {
5999             const float data[4][2] = {{-0.5f, -0.5f}, {0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f}};
6000             for (GLuint i = 0; i < 4; ++i)
6001             {
6002                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6003                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6004             }
6005         }
6006         /* material buffers */
6007         {
6008             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}};
6009             for (GLuint i = 0; i < 4; ++i)
6010             {
6011                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6012                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6013             }
6014         }
6015 
6016         /* vertex buffer */
6017         {
6018             const float data[] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
6019             glGenBuffers(1, &m_vertex_buffer);
6020             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6021             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6022             glBindBuffer(GL_ARRAY_BUFFER, 0);
6023         }
6024 
6025         glBindTexture(GL_TEXTURE_2D, m_rt);
6026         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6027         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6028         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6029         glBindTexture(GL_TEXTURE_2D, 0);
6030         glViewport(0, 0, 100, 100);
6031         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6032         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6033 
6034         glGenVertexArrays(1, &m_vertex_array);
6035         glBindVertexArray(m_vertex_array);
6036         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6037         glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6038         glBindBuffer(GL_ARRAY_BUFFER, 0);
6039         glEnableVertexAttribArray(1);
6040         glBindVertexArray(0);
6041 
6042         glUseProgram(m_program);
6043         glBindVertexArray(m_vertex_array);
6044 
6045         glClear(GL_COLOR_BUFFER_BIT);
6046         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6047         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6048         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6049         if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6050         {
6051             return ERROR;
6052         }
6053 
6054         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6055         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6056         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6057         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6058         {
6059             return ERROR;
6060         }
6061 
6062         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6063         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6064         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6065         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6066         {
6067             return ERROR;
6068         }
6069 
6070         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6071         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6072         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6073         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6074         {
6075             return ERROR;
6076         }
6077 
6078         // once again with only one validation at the end
6079         glClear(GL_COLOR_BUFFER_BIT);
6080         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6081         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6082         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6083 
6084         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6085         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6086         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6087 
6088         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6089         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6090         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6091 
6092         glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6093         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6094         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6095         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6096 
6097         if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6098         {
6099             return ERROR;
6100         }
6101         return NO_ERROR;
6102     }
6103 
Cleanup()6104     virtual long Cleanup()
6105     {
6106         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6107         glUseProgram(0);
6108         glDeleteProgram(m_program);
6109         glDeleteBuffers(8, m_storage_buffer);
6110         glDeleteBuffers(1, &m_vertex_buffer);
6111         glDeleteVertexArrays(1, &m_vertex_array);
6112         glDeleteFramebuffers(1, &m_fbo);
6113         glDeleteTextures(1, &m_rt);
6114         return NO_ERROR;
6115     }
6116 };
6117 
6118 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6119 {
6120     GLuint m_program;
6121     GLuint m_storage_buffer[5];
6122 
Setup()6123     virtual long Setup()
6124     {
6125         m_program = 0;
6126         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6127         return NO_ERROR;
6128     }
6129 
Run()6130     virtual long Run()
6131     {
6132         GLint blocksC;
6133         glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6134         if (blocksC < 8)
6135             return NOT_SUPPORTED;
6136         bool status = true;
6137         const char *const glsl_cs =
6138             NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL
6139                "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL
6140                "};" NL "uniform int g_material_id;" NL "void main() {" NL
6141                "  if (g_material_id == 0) color[gl_LocalInvocationIndex] = g_material[0].color;" NL
6142                "  else if (g_material_id == 1) color[gl_LocalInvocationIndex] = g_material[1].color;" NL
6143                "  else if (g_material_id == 2) color[gl_LocalInvocationIndex] = g_material[2].color;" NL
6144                "  else if (g_material_id == 3) color[gl_LocalInvocationIndex] = g_material[3].color;" NL "}";
6145         m_program = CreateProgramCS(glsl_cs);
6146         glLinkProgram(m_program);
6147         if (!CheckProgram(m_program))
6148             return ERROR;
6149 
6150         glGenBuffers(5, m_storage_buffer);
6151 
6152         /* material buffers */
6153         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}};
6154         for (GLuint i = 0; i < 4; ++i)
6155         {
6156             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6157             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6158         }
6159 
6160         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6161         glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6162 
6163         glUseProgram(m_program);
6164         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6165         glDispatchCompute(1, 1, 1);
6166         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6167         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6168         GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6169         if (!out_data)
6170             return ERROR;
6171         const float *expected = &data[1][0];
6172         for (int i = 0; i < 4; ++i)
6173         {
6174             if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6175                 out_data[i * 4 + 2] != expected[2])
6176             {
6177                 m_context.getTestContext().getLog()
6178                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6179                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6180                     << expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
6181                 status = false;
6182             }
6183         }
6184         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6185         glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6186         glDispatchCompute(1, 1, 1);
6187         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6188         out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6189         if (!out_data)
6190             return ERROR;
6191         expected = &data[3][0];
6192         for (int i = 0; i < 4; ++i)
6193         {
6194             if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6195                 out_data[i * 4 + 2] != expected[2])
6196             {
6197                 m_context.getTestContext().getLog()
6198                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6199                     << ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6200                     << expected[2] << ", " << tcu::TestLog::EndMessage;
6201                 status = false;
6202             }
6203         }
6204 
6205         if (!status)
6206         {
6207             return ERROR;
6208         }
6209         return NO_ERROR;
6210     }
6211 
Cleanup()6212     virtual long Cleanup()
6213     {
6214         glUseProgram(0);
6215         glDeleteProgram(m_program);
6216         glDeleteBuffers(5, m_storage_buffer);
6217         return NO_ERROR;
6218     }
6219 };
6220 
6221 //-----------------------------------------------------------------------------
6222 // 2.5.1 AdvancedReadWriteCase1
6223 //-----------------------------------------------------------------------------
6224 class AdvancedReadWriteCase1VSFS : public ShaderStorageBufferObjectBase
6225 {
6226     GLuint m_program;
6227     GLuint m_storage_buffer;
6228     GLuint m_vertex_array;
6229     GLuint m_vertex_buffer;
6230 
Setup()6231     virtual long Setup()
6232     {
6233         m_program        = 0;
6234         m_storage_buffer = 0;
6235         m_vertex_array   = 0;
6236         m_vertex_buffer  = 0;
6237         return NO_ERROR;
6238     }
6239 
Run()6240     virtual long Run()
6241     {
6242         if (!IsVSFSAvailable(1, 1))
6243             return NOT_SUPPORTED;
6244         const char *const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6245                                        "  vec4 in_color;" NL "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6246                                        "  if (gl_VertexID == 0) {" NL "    g_buffer.out_color = g_buffer.in_color;" NL
6247                                        "    memoryBarrier();" NL "  }" NL "  gl_Position = g_in_position;" NL "}";
6248         const char *const glsl_fs =
6249             NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL "  vec4 in_color;" NL
6250                "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL "  g_fs_out = g_buffer.out_color;" NL "}";
6251         m_program = CreateProgram(glsl_vs, glsl_fs);
6252         glLinkProgram(m_program);
6253         if (!CheckProgram(m_program))
6254             return ERROR;
6255 
6256         glGenBuffers(1, &m_storage_buffer);
6257         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6258         glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6259         float *ptr = reinterpret_cast<float *>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_WRITE_BIT));
6260         if (!ptr)
6261             return ERROR;
6262         *ptr++ = 0.0f;
6263         *ptr++ = 1.0f;
6264         *ptr++ = 0.0f;
6265         *ptr++ = 1.0f;
6266         *ptr++ = 0.0f;
6267         *ptr++ = 0.0f;
6268         *ptr++ = 0.0f;
6269         *ptr++ = 0.0f;
6270         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6271 
6272         /* vertex buffer */
6273         {
6274             const float data[] = {-1, -1, 1, -1, -1, 1, 1, 1};
6275             glGenBuffers(1, &m_vertex_buffer);
6276             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6277             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6278             glBindBuffer(GL_ARRAY_BUFFER, 0);
6279         }
6280 
6281         glGenVertexArrays(1, &m_vertex_array);
6282         glBindVertexArray(m_vertex_array);
6283         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6284         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6285         glBindBuffer(GL_ARRAY_BUFFER, 0);
6286         glEnableVertexAttribArray(0);
6287         glBindVertexArray(0);
6288 
6289         glClear(GL_COLOR_BUFFER_BIT);
6290         glUseProgram(m_program);
6291         glBindVertexArray(m_vertex_array);
6292         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6293         if (!CheckFB(vec3(0, 1, 0)))
6294         {
6295             return ERROR;
6296         }
6297 
6298         ptr = reinterpret_cast<float *>(
6299             glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6300         if (!ptr)
6301             return ERROR;
6302         *ptr++ = 1.0f;
6303         *ptr++ = 0.0f;
6304         *ptr++ = 1.0f;
6305         *ptr++ = 1.0f;
6306         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6307 
6308         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6309         if (!CheckFB(vec3(1, 0, 1)))
6310         {
6311             return ERROR;
6312         }
6313 
6314         return NO_ERROR;
6315     }
6316 
Cleanup()6317     virtual long Cleanup()
6318     {
6319         glUseProgram(0);
6320         glDeleteProgram(m_program);
6321         glDeleteBuffers(1, &m_storage_buffer);
6322         glDeleteBuffers(1, &m_vertex_buffer);
6323         glDeleteVertexArrays(1, &m_vertex_array);
6324         return NO_ERROR;
6325     }
6326 };
6327 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6328 {
6329     GLuint m_program;
6330     GLuint m_storage_buffer;
6331 
Setup()6332     virtual long Setup()
6333     {
6334         m_program        = 0;
6335         m_storage_buffer = 0;
6336         return NO_ERROR;
6337     }
6338 
Run()6339     virtual long Run()
6340     {
6341         bool status               = true;
6342         const char *const glsl_cs = NL
6343             "layout(local_size_x = 128) in;" NL "struct s {" NL "  int ene;" NL "  int due;" NL "  int like;" NL
6344             "  int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL "  s a[128];" NL "} g_buffer;" NL
6345             "void main() {" NL "  g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6346             "  groupMemoryBarrier();" NL "  barrier();" NL "  g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6347             "g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL "  groupMemoryBarrier();" NL "  barrier();" NL
6348             "  g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6349             "= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6350             "128u].like;" NL "}";
6351         m_program = CreateProgramCS(glsl_cs);
6352         glLinkProgram(m_program);
6353         if (!CheckProgram(m_program))
6354             return ERROR;
6355 
6356         glGenBuffers(1, &m_storage_buffer);
6357         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6358         GLint data[128 * 4];
6359         for (int i = 0; i < 128; ++i)
6360         {
6361             data[i * 4]     = i + 256;
6362             data[i * 4 + 1] = 0;
6363             data[i * 4 + 2] = 0;
6364             data[i * 4 + 3] = 0;
6365         }
6366         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6367 
6368         glUseProgram(m_program);
6369         glDispatchCompute(1, 1, 1);
6370         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6371         GLint *out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6372         if (!out_data)
6373             return ERROR;
6374         for (int i = 0; i < 128; ++i)
6375         {
6376             if (out_data[i * 4 + 3] != data[i * 4])
6377             {
6378                 m_context.getTestContext().getLog()
6379                     << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", but expected: " << data[i * 4]
6380                     << " -> " << out_data[i * 4 + 1] << " -> " << out_data[i * 4 + 2] << " -> "
6381                     << tcu::TestLog::EndMessage;
6382                 status = false;
6383             }
6384         }
6385         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6386         for (int i = 0; i < 128; ++i)
6387         {
6388             data[i * 4]     = i + 512;
6389             data[i * 4 + 1] = 0;
6390             data[i * 4 + 2] = 0;
6391             data[i * 4 + 3] = 0;
6392         }
6393         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6394 
6395         glDispatchCompute(1, 1, 1);
6396         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6397         out_data = (GLint *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6398         if (!out_data)
6399             return ERROR;
6400         for (int i = 0; i < 128; ++i)
6401         {
6402             if (out_data[i * 4 + 3] != data[i * 4])
6403             {
6404                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3]
6405                                                     << ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6406                 status = false;
6407             }
6408         }
6409         if (status)
6410             return NO_ERROR;
6411         else
6412             return ERROR;
6413     }
6414 
Cleanup()6415     virtual long Cleanup()
6416     {
6417         glUseProgram(0);
6418         glDeleteProgram(m_program);
6419         glDeleteBuffers(1, &m_storage_buffer);
6420         return NO_ERROR;
6421     }
6422 };
6423 //-----------------------------------------------------------------------------
6424 // 2.6.1 AdvancedUsageCase1
6425 //-----------------------------------------------------------------------------
6426 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6427 {
6428     GLuint m_program;
6429     GLuint m_storage_buffer[3];
6430     GLuint m_vertex_array;
6431     GLuint m_vertex_buffer;
6432     GLuint m_fbo, m_rt;
6433 
Setup()6434     virtual long Setup()
6435     {
6436         m_program = 0;
6437         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6438         m_vertex_array  = 0;
6439         m_vertex_buffer = 0;
6440         glGenFramebuffers(1, &m_fbo);
6441         glGenTextures(1, &m_rt);
6442         return NO_ERROR;
6443     }
6444 
Run()6445     virtual long Run()
6446     {
6447         if (!IsVSFSAvailable(2, 2))
6448             return NOT_SUPPORTED;
6449         const char *const glsl_vs =
6450             NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
6451                "flat out int object_id;" NL "layout(binding = 0) buffer TransformBuffer {" NL
6452                "  mat4 g_transform[4];" NL "};" NL "void main() {" NL "  mat4 mvp = g_transform[g_object_id];" NL
6453                "  gl_Position = mvp * g_position;" NL "  object_id = g_object_id;" NL "}";
6454         const char *const glsl_fs =
6455             NL "flat in int object_id;" NL "layout(location = 0) out vec4 g_fs_out;" NL "struct Material {" NL
6456                "  vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
6457                "  Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
6458                "  int g_material_id[4];" NL "};" NL "void main() {" NL "  int mid = g_material_id[object_id];" NL
6459                "  Material m = g_material[mid];" NL "  g_fs_out = vec4(m.color, 1);" NL "}";
6460         m_program = CreateProgram(glsl_vs, glsl_fs);
6461         glLinkProgram(m_program);
6462         if (!CheckProgram(m_program))
6463             return ERROR;
6464 
6465         glGenBuffers(3, m_storage_buffer);
6466 
6467         /* transform buffer */
6468         {
6469             mat4 data[] = {Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
6470                            Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f)};
6471             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6472             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6473         }
6474         /* material buffer */
6475         {
6476             vec4 data[] = {vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1)};
6477             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6478             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6479         }
6480         /* material id buffer */
6481         {
6482             int data[] = {0, 1, 2, 3};
6483             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6484             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6485         }
6486         /* vertex buffer */
6487         {
6488             struct
6489             {
6490                 vec2 position;
6491                 int object_id;
6492             } 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},
6493                         {vec2(-0.4f, -0.4f), 1}, {vec2(0.4f, -0.4f), 1}, {vec2(-0.4f, 0.4f), 1}, {vec2(0.4f, 0.4f), 1},
6494                         {vec2(-0.4f, -0.4f), 2}, {vec2(0.4f, -0.4f), 2}, {vec2(-0.4f, 0.4f), 2}, {vec2(0.4f, 0.4f), 2},
6495                         {vec2(-0.4f, -0.4f), 3}, {vec2(0.4f, -0.4f), 3}, {vec2(-0.4f, 0.4f), 3}, {vec2(0.4f, 0.4f), 3}};
6496             glGenBuffers(1, &m_vertex_buffer);
6497             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6498             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6499             glBindBuffer(GL_ARRAY_BUFFER, 0);
6500         }
6501 
6502         glBindTexture(GL_TEXTURE_2D, m_rt);
6503         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6504         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6505         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6506         glBindTexture(GL_TEXTURE_2D, 0);
6507         glViewport(0, 0, 100, 100);
6508         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6509         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6510 
6511         glGenVertexArrays(1, &m_vertex_array);
6512         glBindVertexArray(m_vertex_array);
6513         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6514         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
6515         glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void *>(sizeof(vec2)));
6516         glBindBuffer(GL_ARRAY_BUFFER, 0);
6517         glEnableVertexAttribArray(0);
6518         glEnableVertexAttribArray(1);
6519         glBindVertexArray(0);
6520 
6521         glClear(GL_COLOR_BUFFER_BIT);
6522         glUseProgram(m_program);
6523         glBindVertexArray(m_vertex_array);
6524         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6525         glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
6526         glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
6527         glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
6528         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
6529         {
6530             return ERROR;
6531         }
6532         return NO_ERROR;
6533     }
6534 
Cleanup()6535     virtual long Cleanup()
6536     {
6537         glViewport(0, 0, getWindowWidth(), getWindowHeight());
6538         glUseProgram(0);
6539         glDeleteProgram(m_program);
6540         glDeleteBuffers(3, m_storage_buffer);
6541         glDeleteBuffers(1, &m_vertex_buffer);
6542         glDeleteVertexArrays(1, &m_vertex_array);
6543         glDeleteFramebuffers(1, &m_fbo);
6544         glDeleteTextures(1, &m_rt);
6545         return NO_ERROR;
6546     }
6547 };
6548 
6549 //-----------------------------------------------------------------------------
6550 // 2.6.2 AdvancedUsageSync
6551 //-----------------------------------------------------------------------------
6552 class AdvancedUsageSyncVSFS : public ShaderStorageBufferObjectBase
6553 {
6554     GLuint m_program;
6555     GLuint m_storage_buffer[7];
6556     GLuint m_vertex_array;
6557 
Setup()6558     virtual long Setup()
6559     {
6560         m_program = 0;
6561         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6562         m_vertex_array = 0;
6563         return NO_ERROR;
6564     }
6565 
Run()6566     virtual long Run()
6567     {
6568         if (!IsVSFSAvailable(3, 4))
6569             return NOT_SUPPORTED;
6570         const char *const glsl_vs = NL
6571             "layout(std430, binding = 0) coherent buffer Buffer0 {" NL "  int g_data0, g_inc0;" NL
6572             "  int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL
6573             "} g_buffer12[2];" NL "flat out int primitive_id;" NL NL "void Modify(int path) {" NL
6574             "  if (path == 0) {" NL "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL
6575             "  } else if (path == 1) {" NL "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
6576             "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
6577             "  }" NL NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
6578             "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
6579             "void main() {" NL "  Modify(gl_VertexID);" NL "  primitive_id = gl_VertexID;" NL
6580             "  gl_Position = vec4(0, 0, 0, 1);" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "}";
6581         const char *glsl_fs =
6582             NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
6583                "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
6584                "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6585                "  int inc, data;" NL "} g_buffer56[2];" NL "flat in int primitive_id;" NL NL
6586                "void ModifyFS(int path) {" NL "  if (path == 0) {" NL
6587                "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6588                "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6589                "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
6590                "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6591                "  }" NL NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
6592                "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL
6593                "void main() {" NL "  atomicAdd(g_buffer3.data, 1);" NL "  ModifyFS(primitive_id);" NL "}";
6594         m_program = CreateProgram(glsl_vs, glsl_fs);
6595         glLinkProgram(m_program);
6596         if (!CheckProgram(m_program))
6597             return ERROR;
6598 
6599         glGenVertexArrays(1, &m_vertex_array);
6600         glGenBuffers(7, m_storage_buffer);
6601 
6602         /* Buffer0 */
6603         {
6604             int data[4] = {0, 1, 0, 2};
6605             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6606             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6607         }
6608         /* Buffer1 */
6609         {
6610             int data[2] = {3, 1};
6611             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6612             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6613         }
6614         /* Buffer2 */
6615         {
6616             int data[2] = {2, 4};
6617             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6618             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6619         }
6620         /* Buffer3 */
6621         {
6622             int data[1] = {0};
6623             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6624             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6625         }
6626         /* Buffer4 */
6627         {
6628             int data[4] = {0, 1, 0, 2};
6629             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6630             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6631         }
6632         /* Buffer5 */
6633         {
6634             int data[2] = {3, 1};
6635             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6636             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6637         }
6638         /* Buffer6 */
6639         {
6640             int data[2] = {2, 4};
6641             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6642             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6643         }
6644 
6645         glUseProgram(m_program);
6646         glBindVertexArray(m_vertex_array);
6647 
6648         glDrawArrays(GL_POINTS, 0, 3);
6649         glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6650         glDrawArrays(GL_POINTS, 0, 3);
6651         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6652 
6653         /* Buffer0 */
6654         {
6655             const int ref_data[4] = {4, 1, 4, 2};
6656             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6657             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6658             if (!data)
6659                 return ERROR;
6660             for (int i = 0; i < 4; ++i)
6661             {
6662                 if (data[i] != ref_data[i])
6663                 {
6664                     m_context.getTestContext().getLog()
6665                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6666                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6667                     return ERROR;
6668                 }
6669             }
6670             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6671         }
6672         /* Buffer1 */
6673         {
6674             const int ref_data[2] = {3, 5};
6675             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6676             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6677             if (!data)
6678                 return ERROR;
6679             for (int i = 0; i < 2; ++i)
6680             {
6681                 if (data[i] != ref_data[i])
6682                 {
6683                     m_context.getTestContext().getLog()
6684                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6685                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6686                     return ERROR;
6687                 }
6688             }
6689             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6690         }
6691         /* Buffer2 */
6692         {
6693             const int ref_data[2] = {2, 10};
6694             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6695             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6696             if (!data)
6697                 return ERROR;
6698             for (int i = 0; i < 2; ++i)
6699             {
6700                 if (data[i] != ref_data[i])
6701                 {
6702                     m_context.getTestContext().getLog()
6703                         << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6704                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6705                     return ERROR;
6706                 }
6707             }
6708             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6709         }
6710         /* Buffer3 */
6711         {
6712             const int ref_data[1] = {6};
6713             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6714             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6715             if (!data)
6716                 return ERROR;
6717             for (int i = 0; i < 1; ++i)
6718             {
6719                 if (data[i] != ref_data[i])
6720                 {
6721                     m_context.getTestContext().getLog()
6722                         << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6723                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6724                     return ERROR;
6725                 }
6726             }
6727             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6728         }
6729         /* Buffer4 */
6730         {
6731             const int ref_data[4] = {4, 1, 4, 2};
6732             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6733             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6734             if (!data)
6735                 return ERROR;
6736             for (int i = 0; i < 4; ++i)
6737             {
6738                 if (data[i] != ref_data[i])
6739                 {
6740                     m_context.getTestContext().getLog()
6741                         << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6742                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6743                     return ERROR;
6744                 }
6745             }
6746             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6747         }
6748         /* Buffer5 */
6749         {
6750             const int ref_data[2] = {3, 5};
6751             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
6752             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6753             if (!data)
6754                 return ERROR;
6755             for (int i = 0; i < 2; ++i)
6756             {
6757                 if (data[i] != ref_data[i])
6758                 {
6759                     m_context.getTestContext().getLog()
6760                         << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
6761                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6762                     return ERROR;
6763                 }
6764             }
6765             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6766         }
6767         /* Buffer6 */
6768         {
6769             const int ref_data[2] = {2, 10};
6770             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
6771             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6772             if (!data)
6773                 return ERROR;
6774             for (int i = 0; i < 2; ++i)
6775             {
6776                 if (data[i] != ref_data[i])
6777                 {
6778                     m_context.getTestContext().getLog()
6779                         << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
6780                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6781                     return ERROR;
6782                 }
6783             }
6784             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6785         }
6786 
6787         return NO_ERROR;
6788     }
6789 
Cleanup()6790     virtual long Cleanup()
6791     {
6792         glUseProgram(0);
6793         glDeleteProgram(m_program);
6794         glDeleteBuffers(7, m_storage_buffer);
6795         glDeleteVertexArrays(1, &m_vertex_array);
6796         return NO_ERROR;
6797     }
6798 };
6799 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
6800 {
6801     GLuint m_program;
6802     GLuint m_storage_buffer[7];
6803 
Setup()6804     virtual long Setup()
6805     {
6806         m_program = 0;
6807         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6808         return NO_ERROR;
6809     }
6810 
Run()6811     virtual long Run()
6812     {
6813         const char *const glsl_cs =
6814             NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
6815                "  int g_data0, g_inc0;" NL "  int g_data1, g_inc1;" NL "};" NL
6816                "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL "} g_buffer12[2];" NL
6817                "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
6818                "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
6819                "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6820                "  int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL "  if (path == 0) {" NL
6821                "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
6822                "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
6823                "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
6824                "  }" NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
6825                "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
6826                "void Modify2(int path) {" NL "  if (path == 0) {" NL
6827                "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6828                "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6829                "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
6830                "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6831                "  }" NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
6832                "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL NL
6833                "void main() {" NL "  Modify1(int(gl_WorkGroupID.z));" NL "  atomicAdd(g_buffer3.data, 1);" NL
6834                "  Modify2(int(gl_WorkGroupID.z));" NL "}";
6835         m_program = CreateProgramCS(glsl_cs);
6836         glLinkProgram(m_program);
6837         if (!CheckProgram(m_program))
6838             return ERROR;
6839 
6840         glGenBuffers(7, m_storage_buffer);
6841 
6842         /* Buffer0 */
6843         {
6844             int data[4] = {0, 1, 0, 2};
6845             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6846             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6847         }
6848         /* Buffer1 */
6849         {
6850             int data[2] = {3, 1};
6851             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6852             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6853         }
6854         /* Buffer2 */
6855         {
6856             int data[2] = {2, 4};
6857             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6858             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6859         }
6860         /* Buffer3 */
6861         {
6862             int data[1] = {0};
6863             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6864             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6865         }
6866         /* Buffer4 */
6867         {
6868             int data[4] = {0, 1, 0, 2};
6869             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6870             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6871         }
6872         /* Buffer5 */
6873         {
6874             int data[2] = {3, 1};
6875             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6876             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6877         }
6878         /* Buffer6 */
6879         {
6880             int data[2] = {2, 4};
6881             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6882             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6883         }
6884 
6885         glUseProgram(m_program);
6886 
6887         glDispatchCompute(1, 1, 3);
6888         glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6889         glDispatchCompute(1, 1, 3);
6890 
6891         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6892 
6893         /* Buffer0 */
6894         {
6895             const int ref_data[4] = {4, 1, 4, 2};
6896             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6897             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6898             if (!data)
6899                 return ERROR;
6900             for (int i = 0; i < 4; ++i)
6901             {
6902                 if (data[i] != ref_data[i])
6903                 {
6904                     m_context.getTestContext().getLog()
6905                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6906                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6907                     return ERROR;
6908                 }
6909             }
6910             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6911         }
6912         /* Buffer1 */
6913         {
6914             const int ref_data[2] = {3, 5};
6915             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6916             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6917             if (!data)
6918                 return ERROR;
6919             for (int i = 0; i < 2; ++i)
6920             {
6921                 if (data[i] != ref_data[i])
6922                 {
6923                     m_context.getTestContext().getLog()
6924                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6925                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6926                     return ERROR;
6927                 }
6928             }
6929             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6930         }
6931         /* Buffer2 */
6932         {
6933             const int ref_data[2] = {2, 10};
6934             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6935             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6936             if (!data)
6937                 return ERROR;
6938             for (int i = 0; i < 2; ++i)
6939             {
6940                 if (data[i] != ref_data[i])
6941                 {
6942                     m_context.getTestContext().getLog()
6943                         << tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6944                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6945                     return ERROR;
6946                 }
6947             }
6948             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6949         }
6950         /* Buffer3 */
6951         {
6952             const int ref_data[1] = {6};
6953             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6954             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6955             if (!data)
6956                 return ERROR;
6957             for (int i = 0; i < 1; ++i)
6958             {
6959                 if (data[i] != ref_data[i])
6960                 {
6961                     m_context.getTestContext().getLog()
6962                         << tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6963                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6964                     return ERROR;
6965                 }
6966             }
6967             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6968         }
6969         /* Buffer4 */
6970         {
6971             const int ref_data[4] = {4, 1, 4, 2};
6972             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6973             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6974             if (!data)
6975                 return ERROR;
6976             for (int i = 0; i < 4; ++i)
6977             {
6978                 if (data[i] != ref_data[i])
6979                 {
6980                     m_context.getTestContext().getLog()
6981                         << tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6982                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6983                     return ERROR;
6984                 }
6985             }
6986             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6987         }
6988         /* Buffer5 */
6989         {
6990             const int ref_data[2] = {3, 5};
6991             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
6992             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6993             if (!data)
6994                 return ERROR;
6995             for (int i = 0; i < 2; ++i)
6996             {
6997                 if (data[i] != ref_data[i])
6998                 {
6999                     m_context.getTestContext().getLog()
7000                         << tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7001                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7002                     return ERROR;
7003                 }
7004             }
7005             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7006         }
7007         /* Buffer6 */
7008         {
7009             const int ref_data[2] = {2, 10};
7010             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7011             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7012             if (!data)
7013                 return ERROR;
7014             for (int i = 0; i < 2; ++i)
7015             {
7016                 if (data[i] != ref_data[i])
7017                 {
7018                     m_context.getTestContext().getLog()
7019                         << tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7020                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7021                     return ERROR;
7022                 }
7023             }
7024             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7025         }
7026 
7027         return NO_ERROR;
7028     }
7029 
Cleanup()7030     virtual long Cleanup()
7031     {
7032         glUseProgram(0);
7033         glDeleteProgram(m_program);
7034         glDeleteBuffers(7, m_storage_buffer);
7035         return NO_ERROR;
7036     }
7037 };
7038 //-----------------------------------------------------------------------------
7039 // 2.6.3 AdvancedUsageOperators
7040 //-----------------------------------------------------------------------------
7041 class AdvancedUsageOperatorsVS : public ShaderStorageBufferObjectBase
7042 {
7043     GLuint m_program;
7044     GLuint m_storage_buffer[2];
7045     GLuint m_vertex_array;
7046 
Setup()7047     virtual long Setup()
7048     {
7049         m_program = 0;
7050         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7051         m_vertex_array = 0;
7052         return NO_ERROR;
7053     }
7054 
Run()7055     virtual long Run()
7056     {
7057         if (!IsVSFSAvailable(2, 0))
7058             return NOT_SUPPORTED;
7059         const char *const glsl_vs =
7060             NL "layout(std430, binding = 0) buffer Buffer0 {" NL "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL
7061                "layout(std430, binding = 1) buffer Buffer1 {" NL "  int i0;" NL "} g_buffer1;" NL
7062                "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL "  g_o0 += g_i0;" NL
7063                "  g_o0 <<= 1;" NL "  g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL "  g_o0 *= g_i0;" NL
7064                "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7065                "  g_o0 &= g_buffer1.i0;" NL "}";
7066         const char *const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7067                                        "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
7068 
7069         m_program = CreateProgram(glsl_vs, glsl_fs);
7070         glLinkProgram(m_program);
7071         if (!CheckProgram(m_program))
7072             return ERROR;
7073 
7074         glGenVertexArrays(1, &m_vertex_array);
7075         glGenBuffers(2, m_storage_buffer);
7076 
7077         /* Buffer0 */
7078         {
7079             int data[4] = {3, 5};
7080             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7081             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7082         }
7083         /* Buffer1 */
7084         {
7085             int data[1] = {0};
7086             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7087             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7088         }
7089 
7090         glEnable(GL_RASTERIZER_DISCARD);
7091         glUseProgram(m_program);
7092         glBindVertexArray(m_vertex_array);
7093         glDrawArrays(GL_POINTS, 0, 1);
7094         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7095 
7096         /* Buffer0 */
7097         {
7098             const int ref_data[2] = {3, 37};
7099             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7100             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7101             if (!data)
7102                 return ERROR;
7103             for (int i = 0; i < 2; ++i)
7104             {
7105                 if (data[i] != ref_data[i])
7106                 {
7107                     m_context.getTestContext().getLog()
7108                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7109                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7110                     return ERROR;
7111                 }
7112             }
7113             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7114         }
7115         /* Buffer0 */
7116         {
7117             const int ref_data[1] = {0xff2f};
7118             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7119             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7120             if (!data)
7121                 return ERROR;
7122             for (int i = 0; i < 1; ++i)
7123             {
7124                 if (data[i] != ref_data[i])
7125                 {
7126                     m_context.getTestContext().getLog()
7127                         << tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7128                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7129                     return ERROR;
7130                 }
7131             }
7132             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7133         }
7134 
7135         return NO_ERROR;
7136     }
7137 
Cleanup()7138     virtual long Cleanup()
7139     {
7140         glDisable(GL_RASTERIZER_DISCARD);
7141         glUseProgram(0);
7142         glDeleteProgram(m_program);
7143         glDeleteBuffers(2, m_storage_buffer);
7144         glDeleteVertexArrays(1, &m_vertex_array);
7145         return NO_ERROR;
7146     }
7147 };
7148 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7149 {
7150     GLuint m_program;
7151     GLuint m_storage_buffer[2];
7152 
Setup()7153     virtual long Setup()
7154     {
7155         m_program = 0;
7156         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7157         return NO_ERROR;
7158     }
7159 
Run()7160     virtual long Run()
7161     {
7162         const char *const glsl_cs =
7163             NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7164                "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7165                "  int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7166                "  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
7167                "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7168                "  g_o0 &= g_buffer1.i0;" NL "}";
7169 
7170         m_program = CreateProgramCS(glsl_cs);
7171         glLinkProgram(m_program);
7172         if (!CheckProgram(m_program))
7173             return ERROR;
7174 
7175         glGenBuffers(2, m_storage_buffer);
7176 
7177         /* Buffer0 */
7178         {
7179             int data[4] = {3, 5};
7180             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7181             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7182         }
7183         /* Buffer1 */
7184         {
7185             int data[1] = {0};
7186             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7187             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7188         }
7189 
7190         glUseProgram(m_program);
7191         glDispatchCompute(1, 1, 1);
7192         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7193 
7194         /* Buffer0 */
7195         {
7196             const int ref_data[2] = {3, 37};
7197             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7198             int *data = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7199             if (!data)
7200                 return ERROR;
7201             for (int i = 0; i < 2; ++i)
7202             {
7203                 if (data[i] != ref_data[i])
7204                 {
7205                     m_context.getTestContext().getLog()
7206                         << tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7207                         << " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7208                     return ERROR;
7209                 }
7210             }
7211             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7212         }
7213 
7214         return NO_ERROR;
7215     }
7216 
Cleanup()7217     virtual long Cleanup()
7218     {
7219         glUseProgram(0);
7220         glDeleteProgram(m_program);
7221         glDeleteBuffers(2, m_storage_buffer);
7222         return NO_ERROR;
7223     }
7224 };
7225 
7226 //-----------------------------------------------------------------------------
7227 // 2.7 AdvancedUnsizedArrayLength
7228 //-----------------------------------------------------------------------------
7229 template <int stage>
7230 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7231 {
7232     GLuint m_program;
7233     GLuint m_storage_buffer[4];
7234     GLuint m_vertex_array;
7235 
Setup()7236     virtual long Setup()
7237     {
7238         m_program = 0;
7239         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7240         m_vertex_array = 0;
7241         return NO_ERROR;
7242     }
7243 
Cleanup()7244     virtual long Cleanup()
7245     {
7246         glUseProgram(0);
7247         glDeleteProgram(m_program);
7248         glDeleteBuffers(4, m_storage_buffer);
7249         if (stage != compute)
7250             glDeleteVertexArrays(1, &m_vertex_array);
7251         return NO_ERROR;
7252     }
BuildShaderPT(int st)7253     std::string BuildShaderPT(int st)
7254     {
7255         std::ostringstream os;
7256         if (st == vertex)
7257         {
7258             os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7259                      "  gl_PointSize = 1.0f;" NL "#endif";
7260         }
7261         if (st == fragment)
7262         {
7263             os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7264                      "  o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7265         }
7266         os << NL "}";
7267         return os.str();
7268     }
BuildShader()7269     std::string BuildShader()
7270     {
7271         std::ostringstream os;
7272         std::string decl =
7273             NL "layout(std430, binding = 0) readonly buffer Input0 {" NL "  uint g_input0[];" NL "};" NL
7274                "layout(std430, binding = 1) readonly buffer Input23 {" NL "  float data[];" NL "} g_input23[2];" NL
7275                "layout(std430, binding = 3) buffer Output {" NL "  int g_length2;" NL "  int g_length[];" NL "};";
7276         std::string expr = NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input23[0].data.length();" NL
7277                               "  g_length[2] = g_input23[1].data.length();" NL "  g_length2 = g_length.length();";
7278         if (stage == vertex)
7279         {
7280             os << decl
7281                << NL "void main() {" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL
7282                      "  gl_Position = vec4(0,0,0,1);"
7283                << expr;
7284         }
7285         if (stage == fragment)
7286         {
7287             os << NL "layout(location = 0) out vec4 o_color;" << decl
7288                << NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7289         }
7290         if (stage == compute)
7291         {
7292             os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7293         }
7294         os << NL "}";
7295         return os.str();
7296     }
7297 
Run()7298     virtual long Run()
7299     {
7300         const int kSize = 10000;
7301         const int kBufs = 4;
7302         if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7303             return NOT_SUPPORTED;
7304         if (stage == vertex)
7305         {
7306             std::string glsl_vs = BuildShader();
7307             std::string glsl_fs = BuildShaderPT(fragment);
7308             m_program           = CreateProgram(glsl_vs, glsl_fs);
7309         }
7310         else if (stage == fragment)
7311         {
7312             std::string glsl_vs = BuildShaderPT(vertex);
7313             std::string glsl_fs = BuildShader();
7314             m_program           = CreateProgram(glsl_vs, glsl_fs);
7315         }
7316         else
7317         { // compute
7318             std::string glsl_cs = BuildShader();
7319             m_program           = CreateProgramCS(glsl_cs);
7320         }
7321         glLinkProgram(m_program);
7322         if (!CheckProgram(m_program))
7323             return ERROR;
7324         glUseProgram(m_program);
7325 
7326         glGenBuffers(kBufs, m_storage_buffer);
7327         int sizes[kBufs] = {7, 3, 4, 5};
7328         std::vector<int> data(kSize, 41);
7329         for (int i = 0; i < kBufs; ++i)
7330         {
7331             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7332             glBufferData(GL_SHADER_STORAGE_BUFFER, sizes[i] * 4, &data[0], GL_DYNAMIC_COPY);
7333         }
7334 
7335         if (stage != compute)
7336         {
7337             glGenVertexArrays(1, &m_vertex_array);
7338             glBindVertexArray(m_vertex_array);
7339             glDrawArrays(GL_POINTS, 0, 1);
7340         }
7341         else
7342         {
7343             glDispatchCompute(1, 1, 1);
7344         }
7345         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7346 
7347         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7348         int *dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7349         if (!dataout)
7350             return ERROR;
7351         bool status = true;
7352         for (int i = 0; i < kBufs - 1; ++i)
7353             if (dataout[i + 1] != sizes[i])
7354             {
7355                 m_context.getTestContext().getLog()
7356                     << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i + 1] << " should be "
7357                     << sizes[i] << tcu::TestLog::EndMessage;
7358                 status = false;
7359             }
7360         if (dataout[0] != sizes[kBufs - 1] - 1)
7361         {
7362             m_context.getTestContext().getLog()
7363                 << tcu::TestLog::Message << "Array " << (kBufs - 1) << " length is " << dataout[0] << " should be "
7364                 << (sizes[kBufs - 1] - 1) << tcu::TestLog::EndMessage;
7365             status = false;
7366         }
7367         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7368 
7369         if (!status)
7370             return ERROR;
7371 
7372         return NO_ERROR;
7373     }
7374 };
7375 
7376 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7377 {
7378     GLuint m_program;
7379     GLuint m_storage_buffer[8];
7380     GLuint m_vertex_array;
7381     virtual void SetPath() = 0;
7382 
Setup()7383     virtual long Setup()
7384     {
7385         m_program = 0;
7386         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7387         m_vertex_array = 0;
7388         return NO_ERROR;
7389     }
7390 
Cleanup()7391     virtual long Cleanup()
7392     {
7393         glUseProgram(0);
7394         glDeleteProgram(m_program);
7395         glDeleteBuffers(8, m_storage_buffer);
7396         if (stage != compute)
7397             glDeleteVertexArrays(1, &m_vertex_array);
7398         return NO_ERROR;
7399     }
BuildShaderPT(int stagept)7400     std::string BuildShaderPT(int stagept)
7401     {
7402         std::ostringstream os;
7403         if (stagept == vertex)
7404         {
7405             os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7406                      "  gl_PointSize = 1.0f;" NL "#endif";
7407         }
7408         if (stagept == fragment)
7409         {
7410             os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7411                      "  o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7412         }
7413         os << NL "}";
7414         return os.str();
7415     }
BuildShader()7416     std::string BuildShader()
7417     {
7418         std::ostringstream os;
7419         std::string e[4][7] = {{"bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4"},
7420                                {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7421                                {"mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2"},
7422                                {"S0", "S1", "S2", "S2", "S4", "S5", "S6"}};
7423         std::string sd =
7424             NL "struct S0 {" NL "  float f;" NL "  int i;" NL "  uint ui;" NL "  bool b;" NL "};" NL "struct S1 {" NL
7425                "  ivec3 iv;" NL "  bvec2 bv;" NL "  vec4 v;" NL "  uvec2 uv;" NL "};" NL "struct S2 {" NL
7426                "  mat2x2 m22;" NL "  mat4x4 m44;" NL "  mat2x3 m23;" NL "  mat4x2 m42;" NL "  mat3x4 m34;" NL "};" NL
7427                "struct S4 {" NL "  float f[1];" NL "  int i[2];" NL "  uint ui[3];" NL "  bool b[4];" NL
7428                "  ivec3 iv[5];" NL "  bvec2 bv[6];" NL "  vec4  v[7];" NL "  uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7429                "  S0 s0;" NL "  S1 s1;" NL "  S2 s2;" NL "};" NL "struct S6 {" NL "  S4 s4[3];" NL "};";
7430 
7431         std::string lo   = "";
7432         std::string l[4] = {"std140", "std430", "shared", "packed"};
7433         lo += l[layout];
7434         if (etype == matrix_rm)
7435             lo += ", row_major";
7436         std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7437                            ((other_members) ? ("\n  " + e[etype][0] + " pad0;") : "") + NL "  " + e[etype][0] +
7438                            " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7439                            ((other_members) ? ("\n  " + e[etype][1] + " pad1;") : "") + NL "  " + e[etype][1] +
7440                            " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7441                            ((other_members) ? ("\n  " + e[etype][2] + " pad2;") : "") + NL "  " + e[etype][2] +
7442                            " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7443                            ((other_members) ? ("\n  " + e[etype][4] + " pad4;") : "") + NL "  " + e[etype][4] +
7444                            " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7445                            ((other_members) ? ("\n  " + e[etype][5] + " pad5;") : "") + NL "  " + e[etype][5] +
7446                            " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7447                            ((other_members) ? ("\n  " + e[etype][6] + " pad6;") : "") + NL "  " + e[etype][6] +
7448                            " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7449                            "  int g_length[];" NL "};";
7450         std::string expr =
7451             NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7452                "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7453                "  g_length[4] = g_output0.data.length();" NL "  g_length[5] = g_input4.data.length();" NL
7454                "  g_length[6] = g_output1.data.length();";
7455         std::string lastelemexpr =
7456             NL "  g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7457                "  g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7458         if (length_as_index)
7459             expr += lastelemexpr;
7460         if (stage == vertex)
7461         {
7462             os << decl
7463                << NL "void main() {" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL
7464                      "  gl_Position = vec4(0,0,0,1);"
7465                << expr;
7466         }
7467         if (stage == fragment)
7468         {
7469             os << NL "layout(location = 0) out vec4 o_color;" << decl
7470                << NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7471         }
7472         if (stage == compute)
7473         {
7474             os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7475         }
7476         os << NL "}";
7477         return os.str();
7478     }
7479 
Run()7480     virtual long Run()
7481     {
7482         const int kSize = 100000;
7483         const int kBufs = 8;
7484         SetPath();
7485         if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7486             return NOT_SUPPORTED;
7487         GLint blocksC;
7488         glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
7489         GLint minA;
7490         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
7491         if (blocksC < kBufs)
7492             return NOT_SUPPORTED;
7493         if (stage == vertex)
7494         {
7495             std::string glsl_vs = BuildShader();
7496             std::string glsl_fs = BuildShaderPT(fragment);
7497             m_program           = CreateProgram(glsl_vs, glsl_fs);
7498         }
7499         else if (stage == fragment)
7500         {
7501             std::string glsl_vs = BuildShaderPT(vertex);
7502             std::string glsl_fs = BuildShader();
7503             m_program           = CreateProgram(glsl_vs, glsl_fs);
7504         }
7505         else
7506         { // compute
7507             std::string glsl_cs = BuildShader();
7508             m_program           = CreateProgramCS(glsl_cs);
7509         }
7510         glLinkProgram(m_program);
7511         if (!CheckProgram(m_program))
7512             return ERROR;
7513         glUseProgram(m_program);
7514 
7515         glGenBuffers(kBufs, m_storage_buffer);
7516         int sizes[kBufs]        = {7, 5, 3, 4, 23, 123, 419, 8};
7517         int columns[4][kBufs]   = {{1, 1, 1, 1, 1, 1, 1, 1},  // vector: 1 col
7518                                    {2, 3, 4, 4, 2, 3, 4, 1},  // mat: # of cols
7519                                    {2, 3, 4, 4, 3, 2, 2, 1},  // RM mat: # of rows
7520                                    {1, 1, 1, 1, 1, 1, 1, 1}}; // structure: not used
7521         int scalars[4][kBufs]   = {{4, 4, 4, 4, 2, 2, 4, 1},  //vector: size
7522                                    {2, 4, 4, 4, 4, 2, 2, 1},  //matrix column_major: rows
7523                                    {2, 4, 4, 4, 2, 4, 4, 1},  //matrix row_major: columns
7524                                    {1, 1, 1, 1, 1, 1, 1, 1}}; //structure: not used
7525         int mindw[4][kBufs]     = {{3, 4, 3, 3, 2, 2, 4, 1},  // # of real 32bit items
7526                                    {4, 9, 16, 16, 6, 6, 8, 1},
7527                                    {4, 9, 16, 16, 6, 6, 8, 1},
7528                                    {4, 11, 35, 35, 81, 127, 381, 1}};
7529         int std430struct[kBufs] = {4, 16, 48, 48, 88, 68, 264, 1};
7530         int std140struct[kBufs] = {4, 16, 60, 60, 144, 80, 432, 1};
7531         int bufsize[kBufs][2]   = {{0}, {0}};
7532 
7533         std::vector<ivec4> data(kSize, ivec4(41));
7534         for (int i = 0; i < kBufs; ++i)
7535         {
7536             if (layout == std430)
7537             {
7538                 bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
7539                 if (etype == structure)
7540                 {
7541                     bufsize[i][1] = 4 * std430struct[i];
7542                 }
7543             }
7544             else if (layout == std140)
7545             {
7546                 bufsize[i][1] = 4 * columns[etype][i] * 4;
7547                 if (etype == structure)
7548                 {
7549                     bufsize[i][1] = 4 * std140struct[i];
7550                 }
7551             }
7552             else
7553             {
7554                 bufsize[i][1] = 4 * mindw[etype][i];
7555             }
7556             bufsize[i][0] = sizes[i] * bufsize[i][1];
7557             if (i == kBufs - 1 || bind_seq == bindbasebefore)
7558             { // never trim feedback storage
7559                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7560                 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7561             }
7562             else
7563             {
7564                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
7565                 glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7566                 if (bind_seq == bindbaseafter)
7567                 {
7568                     glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7569                 }
7570                 else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
7571                 {
7572                     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
7573                                       bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7574                 }
7575                 else
7576                 { // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
7577                     glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
7578                                       bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7579                 }
7580             }
7581         }
7582 
7583         if (stage != compute)
7584         {
7585             glGenVertexArrays(1, &m_vertex_array);
7586             glBindVertexArray(m_vertex_array);
7587             glDrawArrays(GL_POINTS, 0, 1);
7588         }
7589         else
7590         {
7591             glDispatchCompute(1, 1, 1);
7592         }
7593         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7594 
7595         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
7596         int *dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7597         if (!dataout)
7598             return ERROR;
7599         bool status = true;
7600         for (int i = 0; i < kBufs - 1; ++i)
7601         {
7602             if (other_members)
7603                 sizes[i] -= 1; // space consumed by a pad
7604             if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
7605                 sizes[i] -= 2; // space constrained by offset of range size
7606             if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
7607             {
7608                 m_context.getTestContext().getLog()
7609                     << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
7610                     << sizes[i] << tcu::TestLog::EndMessage;
7611                 status = false;
7612             }
7613             if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
7614             {
7615                 m_context.getTestContext().getLog()
7616                     << tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
7617                     << " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
7618                 status = false;
7619             }
7620         }
7621         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7622 
7623         if (length_as_index)
7624         {
7625             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7626             dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
7627             if (!dataout)
7628                 return ERROR;
7629             int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
7630             if (dataout[i] != 82)
7631             {
7632                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
7633                                                     << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7634                 status = false;
7635             }
7636             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7637             glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7638             dataout = (int *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
7639             if (!dataout)
7640                 return ERROR;
7641             i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
7642             if (dataout[i] != 82)
7643             {
7644                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
7645                                                     << dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7646                 status = false;
7647             }
7648             glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7649         }
7650 
7651         if (!status)
7652             return ERROR;
7653 
7654         return NO_ERROR;
7655     }
7656 
7657 public:
7658     int stage;
7659     int etype;
7660     int layout;
7661     bool other_members;
7662     int bind_seq;
7663     bool length_as_index;
7664 
AdvancedUnsizedArrayLength2()7665     AdvancedUnsizedArrayLength2()
7666         : m_program(0)
7667         , m_vertex_array(0)
7668         , stage(compute)
7669         , etype(vector)
7670         , layout(std430)
7671         , other_members(false)
7672         , bind_seq(bindbasebefore)
7673         , length_as_index(false)
7674     {
7675         for (int i = 0; i < 8; i++)
7676         {
7677             m_storage_buffer[i] = 0;
7678         }
7679     }
7680 };
7681 
7682 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7683 {
7684 public:
SetPath()7685     virtual void SetPath()
7686     {
7687         length_as_index = true;
7688     }
7689 };
7690 
7691 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7692 {
7693 public:
SetPath()7694     virtual void SetPath()
7695     {
7696         bind_seq = bindbaseafter;
7697     }
7698 };
7699 
7700 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7701 {
7702 public:
SetPath()7703     virtual void SetPath()
7704     {
7705         bind_seq = bindrangeoffset;
7706     }
7707 };
7708 
7709 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7710 {
7711 public:
SetPath()7712     virtual void SetPath()
7713     {
7714         bind_seq = bindrangesize;
7715     }
7716 };
7717 
7718 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7719 {
7720 public:
SetPath()7721     virtual void SetPath()
7722     {
7723         etype = vector;
7724     }
7725 };
7726 
7727 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7728 {
7729 public:
SetPath()7730     virtual void SetPath()
7731     {
7732         etype = matrix_cm;
7733     }
7734 };
7735 
7736 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7737 {
7738 public:
SetPath()7739     virtual void SetPath()
7740     {
7741         etype = matrix_rm;
7742     }
7743 };
7744 
7745 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7746 {
7747 public:
SetPath()7748     virtual void SetPath()
7749     {
7750         etype = structure;
7751     }
7752 };
7753 
7754 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7755 {
7756 public:
SetPath()7757     virtual void SetPath()
7758     {
7759         stage  = compute;
7760         layout = std140;
7761     }
7762 };
7763 
7764 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7765 {
7766 public:
SetPath()7767     virtual void SetPath()
7768     {
7769         etype  = matrix_cm;
7770         layout = std140;
7771     }
7772 };
7773 
7774 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7775 {
7776 public:
SetPath()7777     virtual void SetPath()
7778     {
7779         etype  = matrix_rm;
7780         layout = std140;
7781     }
7782 };
7783 
7784 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7785 {
7786 public:
SetPath()7787     virtual void SetPath()
7788     {
7789         etype  = structure;
7790         layout = std140;
7791     }
7792 };
7793 
7794 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7795 {
7796 public:
SetPath()7797     virtual void SetPath()
7798     {
7799         etype  = vector;
7800         layout = packed;
7801     }
7802 };
7803 
7804 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7805 {
7806 public:
SetPath()7807     virtual void SetPath()
7808     {
7809         etype  = matrix_cm;
7810         layout = packed;
7811     }
7812 };
7813 
7814 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7815 {
7816 public:
SetPath()7817     virtual void SetPath()
7818     {
7819         etype  = matrix_rm;
7820         layout = shared;
7821     }
7822 };
7823 
7824 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7825 {
7826 public:
SetPath()7827     virtual void SetPath()
7828     {
7829         stage  = fragment;
7830         etype  = vector;
7831         layout = std430;
7832     }
7833 };
7834 
7835 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7836 {
7837 public:
SetPath()7838     virtual void SetPath()
7839     {
7840         stage         = fragment;
7841         etype         = matrix_cm;
7842         layout        = std430;
7843         other_members = true;
7844     }
7845 };
7846 
7847 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7848 {
7849 public:
SetPath()7850     virtual void SetPath()
7851     {
7852         stage  = fragment;
7853         etype  = matrix_rm;
7854         layout = std140;
7855     }
7856 };
7857 
7858 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7859 {
7860 public:
SetPath()7861     virtual void SetPath()
7862     {
7863         stage  = fragment;
7864         etype  = structure;
7865         layout = std140;
7866     }
7867 };
7868 
7869 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7870 {
7871 public:
SetPath()7872     virtual void SetPath()
7873     {
7874         stage         = vertex;
7875         etype         = vector;
7876         layout        = std430;
7877         other_members = true;
7878     }
7879 };
7880 
7881 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7882 {
7883 public:
SetPath()7884     virtual void SetPath()
7885     {
7886         stage  = vertex;
7887         etype  = matrix_cm;
7888         layout = std140;
7889     }
7890 };
7891 
7892 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7893 {
7894 public:
SetPath()7895     virtual void SetPath()
7896     {
7897         stage  = vertex;
7898         etype  = matrix_rm;
7899         layout = packed;
7900     }
7901 };
7902 
7903 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7904 {
7905 public:
SetPath()7906     virtual void SetPath()
7907     {
7908         stage  = vertex;
7909         etype  = structure;
7910         layout = std140;
7911     }
7912 };
7913 
7914 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7915 {
7916 public:
SetPath()7917     virtual void SetPath()
7918     {
7919         etype         = vector;
7920         other_members = true;
7921     }
7922 };
7923 
7924 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7925 {
7926 public:
SetPath()7927     virtual void SetPath()
7928     {
7929         etype         = matrix_cm;
7930         other_members = true;
7931     }
7932 };
7933 
7934 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7935 {
7936 public:
SetPath()7937     virtual void SetPath()
7938     {
7939         etype         = matrix_rm;
7940         layout        = std140;
7941         other_members = true;
7942     }
7943 };
7944 
7945 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7946 {
7947 public:
SetPath()7948     virtual void SetPath()
7949     {
7950         etype         = structure;
7951         other_members = true;
7952     }
7953 };
7954 
7955 //-----------------------------------------------------------------------------
7956 // 2.8 AdvancedMatrix
7957 //-----------------------------------------------------------------------------
7958 class AdvancedMatrixVSFS : public ShaderStorageBufferObjectBase
7959 {
7960     GLuint m_program;
7961     GLuint m_storage_buffer[3];
7962     GLuint m_vertex_array;
7963     GLuint m_vertex_buffer;
7964     GLuint m_fbo, m_rt;
7965 
Setup()7966     virtual long Setup()
7967     {
7968         m_program = 0;
7969         memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7970         m_vertex_array  = 0;
7971         m_vertex_buffer = 0;
7972         glGenFramebuffers(1, &m_fbo);
7973         glGenTextures(1, &m_rt);
7974         return NO_ERROR;
7975     }
7976 
Run()7977     virtual long Run()
7978     {
7979         if (!IsVSFSAvailable(2, 2))
7980             return NOT_SUPPORTED;
7981         const char *const glsl_vs =
7982             NL "layout(location = 0) in vec4 g_position;" NL "flat out int instance_id;" NL
7983                "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
7984                "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
7985                "layout(binding = 1, std430) readonly buffer Buffer1 {" NL "  mat4 color;" NL "} g_buffer1;" NL
7986                "uniform int g_index1;" NL "uniform int g_index2;" NL "void main() {" NL
7987                "  gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
7988                "  g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
7989                "  if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL "    g_data0[1][1] = 1.0;" NL
7990                "    g_data0[g_index1][g_index2] += 3.0;" NL "  }" NL "  memoryBarrier();" NL
7991                "  instance_id = gl_InstanceID;" NL "}";
7992         const char *const glsl_fs =
7993             NL "flat in int instance_id;" NL "layout(location = 0) out vec4 g_ocolor;" NL
7994                "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
7995                "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
7996                "void main() {" NL "  if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
7997                "  else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
7998                "  else g_ocolor = vec4(g_color[instance_id], 1);" NL "}";
7999         m_program = CreateProgram(glsl_vs, glsl_fs);
8000         glLinkProgram(m_program);
8001         if (!CheckProgram(m_program))
8002             return ERROR;
8003 
8004         glGenBuffers(3, m_storage_buffer);
8005 
8006         /* transform buffer */
8007         {
8008             float data[48 + 16 + 12 + 16] = {
8009                 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,
8010                 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,
8011                 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,
8012             };
8013             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8014             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8015         }
8016         /* transform buffer */
8017         {
8018             float data[16] = {
8019                 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,
8020             };
8021             glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8022             glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8023         }
8024         /* vertex buffer */
8025         {
8026             float data[8] = {-0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f};
8027             glGenBuffers(1, &m_vertex_buffer);
8028             glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8029             glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8030             glBindBuffer(GL_ARRAY_BUFFER, 0);
8031         }
8032 
8033         glBindTexture(GL_TEXTURE_2D, m_rt);
8034         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8035         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8036         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8037         glBindTexture(GL_TEXTURE_2D, 0);
8038         glViewport(0, 0, 100, 100);
8039         glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8040         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
8041 
8042         glGenVertexArrays(1, &m_vertex_array);
8043         glBindVertexArray(m_vertex_array);
8044         glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8045         glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8046         glBindBuffer(GL_ARRAY_BUFFER, 0);
8047         glEnableVertexAttribArray(0);
8048         glBindVertexArray(0);
8049 
8050         glClear(GL_COLOR_BUFFER_BIT);
8051         glUseProgram(m_program);
8052         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8053         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8054 
8055         glBindVertexArray(m_vertex_array);
8056         glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8057         if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8058         {
8059             return ERROR;
8060         }
8061         return NO_ERROR;
8062     }
8063 
Cleanup()8064     virtual long Cleanup()
8065     {
8066         glViewport(0, 0, getWindowWidth(), getWindowHeight());
8067         glUseProgram(0);
8068         glDeleteProgram(m_program);
8069         glDeleteBuffers(3, m_storage_buffer);
8070         glDeleteBuffers(1, &m_vertex_buffer);
8071         glDeleteVertexArrays(1, &m_vertex_array);
8072         glDeleteFramebuffers(1, &m_fbo);
8073         glDeleteTextures(1, &m_rt);
8074         return NO_ERROR;
8075     }
8076 };
8077 
8078 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8079 {
8080     GLuint m_program;
8081     GLuint m_storage_buffer;
8082 
Setup()8083     virtual long Setup()
8084     {
8085         m_program        = 0;
8086         m_storage_buffer = 0;
8087         return NO_ERROR;
8088     }
8089 
Run()8090     virtual long Run()
8091     {
8092         bool status = true;
8093         const char *const glsl_cs =
8094             NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL "  mat4x3 dst4x3;" NL
8095                "  mat4 dst4;" NL "  mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8096                "void main() {" NL "  b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8097                "  b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8098                "  b.dst4[g_index2][g_index1] = 17.0;" NL "  b.dst4[g_index2][g_index1] += 6.0;" NL
8099                "  b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL "  b.dst4[3][1] = b.src4[3][1];" NL "}";
8100         m_program = CreateProgramCS(glsl_cs);
8101         glLinkProgram(m_program);
8102         if (!CheckProgram(m_program))
8103             return ERROR;
8104 
8105         glGenBuffers(1, &m_storage_buffer);
8106         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8107         GLfloat data[16 + 16 + 16];
8108         for (int i = 0; i < 32; ++i)
8109             data[i] = 0.0f;
8110         for (int i = 32; i < 48; ++i)
8111             data[i] = (GLfloat)i;
8112         glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8113 
8114         glUseProgram(m_program);
8115         glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8116         glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8117         glDispatchCompute(1, 1, 1);
8118         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8119         GLfloat *out_data = (GLfloat *)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8120         if (!out_data)
8121             return ERROR;
8122         GLfloat expected[32] = {
8123             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,
8124 
8125             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};
8126         for (int i = 0; i < 32; ++i)
8127         {
8128             if (out_data[i] != expected[i])
8129             {
8130                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8131                                                     << ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8132                 status = false;
8133             }
8134         }
8135         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8136         if (status)
8137             return NO_ERROR;
8138         else
8139             return ERROR;
8140     }
8141 
Cleanup()8142     virtual long Cleanup()
8143     {
8144         glUseProgram(0);
8145         glDeleteProgram(m_program);
8146         glDeleteBuffers(1, &m_storage_buffer);
8147         return NO_ERROR;
8148     }
8149 };
8150 
8151 //-----------------------------------------------------------------------------
8152 // 4.1.1 NegativeAPIBind
8153 //-----------------------------------------------------------------------------
8154 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8155 {
Run()8156     virtual long Run()
8157     {
8158         GLint bindings;
8159         GLint alignment;
8160         GLuint buffer;
8161         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8162         m_context.getTestContext().getLog()
8163             << tcu::TestLog::Message << "Max storage buffer bindings " << bindings << tcu::TestLog::EndMessage;
8164         glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8165         m_context.getTestContext().getLog()
8166             << tcu::TestLog::Message << "Storage buffer offset alignment " << alignment << tcu::TestLog::EndMessage;
8167 
8168         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8169         if (glGetError() != GL_INVALID_VALUE)
8170         {
8171             m_context.getTestContext().getLog()
8172                 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8173                 << "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8174                 << "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8175             return ERROR;
8176         }
8177 
8178         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8179         if (glGetError() != GL_INVALID_VALUE)
8180         {
8181             m_context.getTestContext().getLog()
8182                 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8183                 << "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8184                 << "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8185             return ERROR;
8186         }
8187 
8188         glGenBuffers(1, &buffer);
8189         glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, alignment - 1, 0);
8190         if (glGetError() != GL_INVALID_VALUE)
8191         {
8192             m_context.getTestContext().getLog()
8193                 << tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8194                 << "SHADER_STORAGE_BUFFER and <offset>  is not a multiple of the value of\n"
8195                 << "SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT." << tcu::TestLog::EndMessage;
8196             return ERROR;
8197         }
8198 
8199         return NO_ERROR;
8200     }
8201 };
8202 
8203 //-----------------------------------------------------------------------------
8204 // 4.2.1 NegativeGLSLCompileTime
8205 //-----------------------------------------------------------------------------
8206 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8207 {
Shader1(int binding)8208     static std::string Shader1(int binding)
8209     {
8210         std::stringstream ss;
8211         ss << NL "layout(binding = " << binding
8212            << ") buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8213         return ss.str();
8214     }
8215 
Shader2(int binding)8216     static std::string Shader2(int binding)
8217     {
8218         std::stringstream ss;
8219         ss << NL "layout(binding = " << binding
8220            << ") buffer Buffer {" NL "  int x;" NL "} g_array[4];" NL "void main() {" NL "  g_array[0].x = 0;" NL
8221               "  g_array[1].x = 0;" NL "  g_array[2].x = 0;" NL "  g_array[3].x = 0;" NL "}";
8222         return ss.str();
8223     }
8224 
Run()8225     virtual long Run()
8226     {
8227         GLint bindings;
8228         glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8229 
8230         //  initialization of buffer block member 'x' not allowed
8231         if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL "  x = 0;" NL "}"))
8232             return ERROR;
8233 
8234         //  syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8235         if (!Compile(Shader1(-1)))
8236             return ERROR;
8237         //  invalid value 96 for layout specifier 'binding'
8238         if (!Compile(Shader1(bindings)))
8239             return ERROR;
8240 
8241         //  invalid value 98 for layout specifier 'binding'
8242         if (!Compile(Shader2(bindings - 2)))
8243             return ERROR;
8244 
8245         //  OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8246         if (!Compile(NL "buffer int x;" NL "void main() {" NL "  x = 0;" NL "}"))
8247             return ERROR;
8248 
8249         // OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8250         if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL "  y = 0;" NL "  buffer int x = 0;" NL "}"))
8251             return ERROR;
8252 
8253         //  OpenGL does not allow a parameter to be a buffer
8254         if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL "  atomicAdd(a, 1);" NL "}" NL
8255                         "void main() {" NL "  Modify(y);" NL "}"))
8256             return ERROR;
8257 
8258         //  layout specifier 'std430', incompatible with 'uniform blocks'
8259         if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8260                         "  y = x;" NL "}"))
8261             return ERROR;
8262 
8263         //  unknown layout specifier 'std430'
8264         if (!Compile(NL "buffer SSBO {" NL "  layout(std430) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8265             return ERROR;
8266 
8267         //  unknown layout specifier 'binding = 1'
8268         if (!Compile(NL "buffer SSBO {" NL "  layout(binding = 1) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL
8269                         "}"))
8270             return ERROR;
8271 
8272         //  OpenGL does not allow writing to readonly variable 'x'
8273         if (!Compile(NL "readonly buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8274             return ERROR;
8275 
8276         //  OpenGL does not allow reading writeonly variable 'y'
8277         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "writeonly buffer SSBO2 {" NL "  int y;" NL "};" NL
8278                         "void main() {" NL "  x = y;" NL "}"))
8279             return ERROR;
8280 
8281         //  OpenGL does not allow writing to readonly variable 'z'
8282         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "buffer SSBO2 {" NL "  writeonly int y;" NL
8283                         "  readonly int z;" NL "};" NL "void main() {" NL "  x = y;" NL "  z = 0;" NL "}"))
8284             return ERROR;
8285 
8286         //  OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8287         if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "readonly buffer SSBO2 {" NL "  writeonly int y;" NL
8288                         "};" NL "void main() {" NL "  x = y;" NL "}"))
8289             return ERROR;
8290 
8291         // ["layout(binding = 1) buffer;" should cause compile-time error
8292         if (!Compile(NL "layout(binding = 1) buffer;" //
8293                      NL "buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8294             return ERROR;
8295 
8296         // ["  atomicAdd(y, 2);"  should cause compile-time error
8297         if (!Compile(NL "buffer coherent Buffer { int x; };" NL "int y;" NL "void main() {" NL "  atomicAdd(x, 1);" NL
8298                         "  atomicAdd(y, 2);" //
8299                      NL "}"))
8300             return ERROR;
8301 
8302         if (!Compile( // can't construct vector from an array
8303                 NL "buffer b {" NL "  vec4 x[10];" NL "};" NL "void main() {" NL "  vec4 y = vec4(x);" NL "}"))
8304             return ERROR;
8305 
8306         if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8307                 NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
8308                    "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
8309                    "void main() {" NL "  for (int i = 0; i < 4; ++i) {" NL
8310                    "    g_output[i].data0 = g_input[i].data0;" NL "  }" NL "}"))
8311             return ERROR;
8312 
8313         if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8314                 NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL "} g_material[4];" NL
8315                    "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL "};" NL
8316                    "uniform int g_material_id;" NL "void main() {" NL
8317                    "  color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}"))
8318             return ERROR;
8319 
8320         return NO_ERROR;
8321     }
Compile(const std::string & source)8322     bool Compile(const std::string &source)
8323     {
8324         const char *const csVer  = "#version 310 es" NL "layout(local_size_x = 1) in;";
8325         const char *const src[2] = {csVer, source.c_str()};
8326         const GLuint sh          = glCreateShader(GL_COMPUTE_SHADER);
8327         glShaderSource(sh, 2, src, NULL);
8328         glCompileShader(sh);
8329 
8330         GLchar log[1024];
8331         glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8332         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8333                                             << log << tcu::TestLog::EndMessage;
8334 
8335         GLint status;
8336         glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8337         glDeleteShader(sh);
8338 
8339         if (status == GL_TRUE)
8340         {
8341             m_context.getTestContext().getLog()
8342                 << tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8343             return false;
8344         }
8345 
8346         return true;
8347     }
8348 };
8349 
8350 //-----------------------------------------------------------------------------
8351 // 4.2.2 NegativeGLSLLinkTime
8352 //-----------------------------------------------------------------------------
8353 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8354 {
Run()8355     virtual long Run()
8356     {
8357         if (!IsVSFSAvailable(1, 1))
8358             return NOT_SUPPORTED;
8359         if (!Link("#version 310 es" NL "buffer Buffer { int x; };" NL "void main() {" NL "  x += 2;" NL "}",
8360                   "#version 310 es" NL "precision highp float;" NL "buffer Buffer { uint x; };" NL "void main() {" NL
8361                   "  x += 3u;" NL "}"))
8362             return ERROR;
8363 
8364         if (!Link("#version 310 es" NL "buffer Buffer { int x; int y; };" NL "void main() {" NL "  x += 2;" NL "}",
8365                   "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x; };" NL "void main() {" NL
8366                   "  x += 3;" NL "}"))
8367             return ERROR;
8368 
8369         if (!Link("#version 310 es" NL "buffer Buffer { int y; };" NL "void main() {" NL "  y += 2;" NL "}",
8370                   "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x; };" NL "void main() {" NL
8371                   "  x += 3;" NL "}"))
8372             return ERROR;
8373 
8374         if (!Link("#version 310 es" NL "buffer Buffer { int x[2]; };" NL "void main() {" NL "  x[1] += 2;" NL "}",
8375                   "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x[3]; };" NL "void main() {" NL
8376                   "  x[1] += 3;" NL "}"))
8377             return ERROR;
8378 
8379         return NO_ERROR;
8380     }
Link(const std::string & cs0,const std::string & cs1)8381     bool Link(const std::string &cs0, const std::string &cs1)
8382     {
8383         const GLuint p = glCreateProgram();
8384 
8385         /* shader 0 */
8386         {
8387             GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8388             glAttachShader(p, sh);
8389             glDeleteShader(sh);
8390             const char *const src = cs0.c_str();
8391             glShaderSource(sh, 1, &src, NULL);
8392             glCompileShader(sh);
8393 
8394             GLint status;
8395             glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8396             if (status == GL_FALSE)
8397             {
8398                 m_context.getTestContext().getLog()
8399                     << tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
8400                 CheckProgram(p);
8401                 glDeleteProgram(p);
8402                 return false;
8403             }
8404         }
8405         /* shader 1 */
8406         {
8407             GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8408             glAttachShader(p, sh);
8409             glDeleteShader(sh);
8410             const char *const src = cs1.c_str();
8411             glShaderSource(sh, 1, &src, NULL);
8412             glCompileShader(sh);
8413 
8414             GLint status;
8415             glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8416             if (status == GL_FALSE)
8417             {
8418                 m_context.getTestContext().getLog()
8419                     << tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
8420                 CheckProgram(p);
8421                 glDeleteProgram(p);
8422                 return false;
8423             }
8424         }
8425 
8426         glLinkProgram(p);
8427 
8428         GLchar log[1024];
8429         glGetProgramInfoLog(p, sizeof(log), NULL, log);
8430         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
8431                                             << log << tcu::TestLog::EndMessage;
8432 
8433         GLint status;
8434         glGetProgramiv(p, GL_LINK_STATUS, &status);
8435         glDeleteProgram(p);
8436 
8437         if (status == GL_TRUE)
8438         {
8439             m_context.getTestContext().getLog()
8440                 << tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
8441             return false;
8442         }
8443 
8444         return true;
8445     }
8446 };
8447 } // anonymous namespace
8448 
ShaderStorageBufferObjectTests(deqp::Context & context)8449 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context &context)
8450     : TestCaseGroup(context, "shader_storage_buffer_object", "")
8451 {
8452 }
8453 
~ShaderStorageBufferObjectTests(void)8454 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8455 {
8456 }
8457 
init()8458 void ShaderStorageBufferObjectTests::init()
8459 {
8460     using namespace deqp;
8461     addChild(new TestSubcase(m_context, "basic-basic-vs", TestSubcase::Create<BasicBasicVS>));
8462     addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
8463     addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
8464     addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
8465     addChild(new TestSubcase(m_context, "basic-syntax-vs", TestSubcase::Create<BasicSyntaxVS>));
8466     addChild(new TestSubcase(m_context, "basic-syntax-cs", TestSubcase::Create<BasicSyntaxCS>));
8467     addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
8468     addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
8469     addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
8470     addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
8471     addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
8472     addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
8473     addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
8474     addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
8475     addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
8476     addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
8477     addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
8478     addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
8479     addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
8480     addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
8481     addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
8482     addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
8483     addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
8484     addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
8485     addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
8486     addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
8487     addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
8488     addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
8489     addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
8490     addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
8491     addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
8492     addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
8493     addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
8494     addChild(new TestSubcase(m_context, "basic-atomic-case1-vsfs", TestSubcase::Create<BasicAtomicCase1VSFS>));
8495     addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
8496     addChild(new TestSubcase(m_context, "basic-atomic-case3-vsfs", TestSubcase::Create<BasicAtomicCase3VSFS>));
8497     addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
8498     addChild(new TestSubcase(m_context, "basic-atomic-case4-vsfs", TestSubcase::Create<BasicAtomicCase4VSFS>));
8499     addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
8500     addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
8501     addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
8502     addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
8503     addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
8504     addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
8505     addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
8506     addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
8507     addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
8508     addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
8509     addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
8510     addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
8511     addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
8512     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
8513                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
8514     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
8515                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
8516     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
8517                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
8518     addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
8519                              TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
8520     addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
8521                              TestSubcase::Create<BasicMatrixOperationsCase1VS>));
8522     addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
8523                              TestSubcase::Create<BasicMatrixOperationsCase1CS>));
8524     addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
8525                              TestSubcase::Create<BasicMatrixOperationsCase2VS>));
8526     addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
8527                              TestSubcase::Create<BasicMatrixOperationsCase2CS>));
8528     addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
8529                              TestSubcase::Create<BasicMatrixOperationsCase3VS>));
8530     addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
8531                              TestSubcase::Create<BasicMatrixOperationsCase3CS>));
8532     addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
8533                              TestSubcase::Create<BasicMatrixOperationsCase4VS>));
8534     addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
8535                              TestSubcase::Create<BasicMatrixOperationsCase4CS>));
8536     addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
8537                              TestSubcase::Create<BasicMatrixOperationsCase5VS>));
8538     addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
8539                              TestSubcase::Create<BasicMatrixOperationsCase5CS>));
8540     addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
8541                              TestSubcase::Create<BasicMatrixOperationsCase6VS>));
8542     addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
8543                              TestSubcase::Create<BasicMatrixOperationsCase6CS>));
8544     addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
8545                              TestSubcase::Create<BasicMatrixOperationsCase7VS>));
8546     addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
8547                              TestSubcase::Create<BasicMatrixOperationsCase7CS>));
8548     addChild(new TestSubcase(m_context, "advanced-switchBuffers-vs", TestSubcase::Create<AdvancedSwitchBuffersVS>));
8549     addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
8550     addChild(new TestSubcase(m_context, "advanced-switchPrograms-vs", TestSubcase::Create<AdvancedSwitchProgramsVS>));
8551     addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
8552     addChild(new TestSubcase(m_context, "advanced-write-fragment-fs", TestSubcase::Create<AdvancedWriteFragmentFS>));
8553     addChild(new TestSubcase(m_context, "advanced-write-fragment-cs", TestSubcase::Create<AdvancedWriteFragmentCS>));
8554     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-vs",
8555                              TestSubcase::Create<AdvancedIndirectAddressingCase1VS>));
8556     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
8557                              TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
8558     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-vsfs",
8559                              TestSubcase::Create<AdvancedIndirectAddressingCase2VSFS>));
8560     addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
8561                              TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
8562     addChild(
8563         new TestSubcase(m_context, "advanced-readWrite-case1-vsfs", TestSubcase::Create<AdvancedReadWriteCase1VSFS>));
8564     addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
8565     addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
8566     addChild(new TestSubcase(m_context, "advanced-usage-sync-vsfs", TestSubcase::Create<AdvancedUsageSyncVSFS>));
8567     addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
8568     addChild(new TestSubcase(m_context, "advanced-usage-operators-vs", TestSubcase::Create<AdvancedUsageOperatorsVS>));
8569     addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
8570     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-int",
8571                              TestSubcase::Create<AdvancedUnsizedArrayLength<compute>>));
8572     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-int",
8573                              TestSubcase::Create<AdvancedUnsizedArrayLength<fragment>>));
8574     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-int",
8575                              TestSubcase::Create<AdvancedUnsizedArrayLength<vertex>>));
8576     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
8577                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
8578     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
8579                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
8580     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
8581                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
8582     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
8583                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
8584     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
8585                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
8586     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
8587                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
8588     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
8589                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
8590     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
8591                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
8592     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
8593                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
8594     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
8595                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
8596     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
8597                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
8598     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
8599                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
8600     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
8601                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
8602     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
8603                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
8604     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
8605                              TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
8606     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
8607                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
8608     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
8609                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
8610     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
8611                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
8612     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
8613                              TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
8614     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
8615                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
8616     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
8617                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
8618     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
8619                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
8620     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
8621                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
8622 
8623     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
8624                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
8625 
8626     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
8627                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
8628 
8629     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
8630                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
8631 
8632     addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
8633                              TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
8634 
8635     addChild(new TestSubcase(m_context, "advanced-matrix-vsfs", TestSubcase::Create<AdvancedMatrixVSFS>));
8636     addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
8637     addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
8638     addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
8639     addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
8640 }
8641 
8642 } // namespace es31compatibility
8643 } // namespace gl4cts
8644