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