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