1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
24 #include "gl4cES31CompatibilityTests.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuMatrix.hpp"
27 #include "tcuRenderTarget.hpp"
35 namespace es31compatibility
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;
77 static tcu::TestLog* currentLog;
78 void setOutput(tcu::TestLog& log)
83 void Output(const char* format, ...)
86 va_start(args, format);
88 const int MAX_OUTPUT_STRING_SIZE = 40000;
89 static char temp[MAX_OUTPUT_STRING_SIZE];
91 vsnprintf(temp, MAX_OUTPUT_STRING_SIZE - 1, format, args);
92 temp[MAX_OUTPUT_STRING_SIZE - 1] = '\0';
94 char* logLine = strtok(temp, "\n");
95 while (logLine != NULL)
97 currentLog->writeMessage(logLine);
98 logLine = strtok(NULL, "\n");
103 const char* const kGLSLVer = "#version 310 es" NL "precision highp float;" NL "precision highp int;";
105 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
107 virtual std::string Title()
112 virtual std::string Purpose()
117 virtual std::string Method()
122 virtual std::string PassCriteria()
128 bool IsVSFSAvailable(int requiredVS, int requiredFS)
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)
137 std::ostringstream reason;
138 reason << "Required " << requiredVS << " VS storage blocks but only " << blocksVS << " available."
140 << "Required " << requiredFS << " FS storage blocks but only " << blocksFS << " available."
142 OutputNotSupported(reason.str());
149 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
150 return renderTarget.getWidth();
153 int getWindowHeight()
155 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
156 return renderTarget.getHeight();
159 bool CheckProgram(GLuint program)
162 glGetProgramiv(program, GL_LINK_STATUS, &status);
164 if (status == GL_FALSE)
166 GLint attached_shaders;
167 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
169 if (attached_shaders > 0)
171 std::vector<GLuint> shaders(attached_shaders);
172 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
174 for (GLint i = 0; i < attached_shaders; ++i)
177 glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
180 case GL_VERTEX_SHADER:
181 Output("*** Vertex Shader ***\n");
183 case GL_FRAGMENT_SHADER:
184 Output("*** Fragment Shader ***\n");
186 case GL_COMPUTE_SHADER:
187 Output("*** Compute Shader ***\n");
190 Output("*** Unknown Shader ***\n");
194 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
197 std::vector<GLchar> source(length);
198 glGetShaderSource(shaders[i], length, NULL, &source[0]);
199 Output("%s\n", &source[0]);
201 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
204 std::vector<GLchar> log(length);
205 glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
206 Output("%s\n", &log[0]);
211 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
214 std::vector<GLchar> log(length);
215 glGetProgramInfoLog(program, length, NULL, &log[0]);
216 Output("%s\n", &log[0]);
220 return status == GL_TRUE ? true : false;
223 GLuint CreateProgram(const std::string& vs, const std::string& fs)
225 const GLuint p = glCreateProgram();
229 const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
230 glAttachShader(p, sh);
232 const char* const src[2] = { kGLSLVer, vs.c_str() };
233 glShaderSource(sh, 2, src, NULL);
238 const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
239 glAttachShader(p, sh);
241 const char* const src[2] = { kGLSLVer, fs.c_str() };
242 glShaderSource(sh, 2, src, NULL);
248 GLuint CreateProgramCS(const std::string& cs)
250 const GLuint p = glCreateProgram();
254 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
255 glAttachShader(p, sh);
257 const char* const src[2] = { kGLSLVer, cs.c_str() };
258 glShaderSource(sh, 2, src, NULL);
264 GLuint BuildShaderProgram(GLenum type, const std::string& source)
266 const char* const src[2] = { kGLSLVer, source.c_str() };
267 return glCreateShaderProgramv(type, 2, src);
270 bool ColorEqual(int x, int y, const vec3& c0, const vec3& expected, const vec3& epsilon, const vec3& color_max)
273 if (fabs(c0[0] / color_max[0] - expected[0]) > epsilon[0])
275 if (fabs(c0[1] / color_max[1] - expected[1]) > epsilon[1])
277 if (fabs(c0[2] / color_max[2] - expected[2]) > epsilon[2])
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],
289 bool CheckFB(vec3 expected)
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)
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])
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]);
318 bool ValidateWindow4Quads(const vec3& lb, const vec3& rb, const vec3& rt, const vec3& lt, int* bad_pixels = NULL)
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);
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]);
335 for (int y = 10, i = (100 * 10 + 10) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
337 for (int x = 10; x < width / 2 - 10; ++x, i += 4)
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))
349 Output("Left-bottom quad checking failed. Bad pixels: %d", bad);
353 for (int y = 10, i = (100 * 10 + 60) * 4; y < height / 2 - 10; ++y, i += 70 * 4)
355 for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
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))
367 Output("right-bottom quad checking failed. Bad pixels: %d", bad);
371 for (int y = height / 2 + 10, i = (100 * 60 + 60) * 4; y < height - 10; ++y, i += 70 * 4)
373 for (int x = width / 2 + 10; x < width - 10; ++x, i += 4)
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))
385 Output("right-top quad checking failed. Bad pixels: %d", bad);
389 for (int y = height / 2 + 10, i = (100 * 60 + 10) * 4; y < height - 10; ++y, i += 70 * 4)
391 for (int x = 10; x < width / 2 - 10; ++x, i += 4)
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))
403 Output("left-top quad checking failed. Bad pixels: %d", bad);
406 // middle horizontal line should be black
407 for (int y = height / 2 - 2, i = (100 * 48) * 4; y < height / 2 + 2; ++y)
409 for (int x = 0; x < width; ++x, i += 4)
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))
421 Output("middle horizontal line checking failed. Bad pixels: %d", bad);
424 // middle vertical line should be black
425 for (int y = 0, i = 48 * 4; y < height; ++y, i += 96 * 4)
427 for (int x = width / 2 - 2; x < width / 2 + 2; ++x, i += 4)
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))
439 Output("middle vertical line checking failed. Bad pixels: %d", bad);
445 Output("Bad pixels:%d, counted bad:%d\n", bad_pixels == NULL ? 0 : *bad_pixels, bad);
449 const mat4 Translation(float tx, float ty, float tz)
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 };
455 const char* GLenumToString(GLenum e)
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";
490 //-----------------------------------------------------------------------------
492 //-----------------------------------------------------------------------------
493 class BasicBasicVS : public ShaderStorageBufferObjectBase
497 GLuint m_vertex_array;
509 if (!IsVSFSAvailable(1, 0))
510 return NOT_SUPPORTED;
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))
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);
528 glGenVertexArrays(1, &m_vertex_array);
529 glBindVertexArray(m_vertex_array);
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);
537 if (!CheckFB(vec3(0, 1, 0)))
543 virtual long Cleanup()
546 glDeleteProgram(m_program);
547 glDeleteBuffers(1, &m_buffer);
548 glDeleteVertexArrays(1, &m_vertex_array);
553 class BasicBasicCS : public ShaderStorageBufferObjectBase
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))
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);
579 glUseProgram(m_program);
580 glDispatchCompute(1, 1, 1);
581 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
583 GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
592 virtual long Cleanup()
595 glDeleteProgram(m_program);
596 glDeleteBuffers(1, &m_buffer);
601 //-----------------------------------------------------------------------------
603 //-----------------------------------------------------------------------------
604 class BasicMax : public ShaderStorageBufferObjectBase
606 bool Check(GLenum e, GLint64 value, bool max_value)
613 glGetIntegerv(e, &i);
614 glGetInteger64v(e, &i64);
616 glGetBooleanv(e, &b);
621 if (static_cast<GLint64>(i) < value)
625 if (static_cast<GLint64>(f) < value)
630 Output("%s is %d should be at least %d.\n", GLenumToString(e), i, static_cast<GLint>(value));
635 if (static_cast<GLint64>(i) > value)
639 if (static_cast<GLint64>(f) > value)
644 Output("%s is %d should be at most %d.\n", GLenumToString(e), i, static_cast<GLint>(value));
652 if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
654 if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 0, true))
656 if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 4, true))
658 if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 4, true))
660 if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 134217728 /* 2^27 */, true))
662 if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 4, true))
664 if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4, true))
666 if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
671 //-----------------------------------------------------------------------------
673 //-----------------------------------------------------------------------------
674 class BasicBinding : public ShaderStorageBufferObjectBase
678 bool Check(GLenum e, GLuint expected)
685 GLfloat expectedFloat = static_cast<GLfloat>(expected);
687 glGetIntegerv(e, &i);
688 glGetInteger64v(e, &i64);
690 glGetBooleanv(e, &b);
693 if (static_cast<GLuint>(i) != expected)
695 if (static_cast<GLuint>(i64) != expected)
697 if (static_cast<GLuint>(f) != expectedFloat)
699 if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
704 Output("%s is %d should be %d.\n", GLenumToString(e), i, expected);
709 bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
714 glGetIntegeri_v(e, index, &i);
715 glGetInteger64i_v(e, index, &i64);
718 if (static_cast<GLuint>(i) != expected)
720 if (static_cast<GLuint>(i64) != expected)
725 Output("%s at index %d is %d should be %d.\n", GLenumToString(e), index, i, expected);
732 memset(m_buffer, 0, sizeof(m_buffer));
738 GLint maxShaderStorageBufferBindings = 0;
739 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
741 // check default state
742 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
744 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
746 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
748 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
750 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
754 glGenBuffers(4, m_buffer);
755 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
757 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
759 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
761 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
763 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
765 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
768 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
770 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
772 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
774 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
776 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
780 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
782 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
784 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
786 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
788 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
790 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
793 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
795 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
797 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
799 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
801 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
804 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
806 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
808 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
810 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
812 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
816 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
817 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
819 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
821 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
823 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
826 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
827 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
829 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
831 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
833 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
836 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
837 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
839 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
841 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
843 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
846 glDeleteBuffers(4, m_buffer);
847 memset(m_buffer, 0, sizeof(m_buffer));
849 if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
851 for (GLint i = 0; i < maxShaderStorageBufferBindings; ++i)
853 if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
860 virtual long Cleanup()
862 glDeleteBuffers(4, m_buffer);
867 //-----------------------------------------------------------------------------
869 //-----------------------------------------------------------------------------
870 class BasicSyntaxVS : public ShaderStorageBufferObjectBase
874 GLuint m_vertex_array;
876 bool RunIteration(const char* vs, const char* fs)
879 glDeleteProgram(m_program);
880 m_program = CreateProgram(vs, fs);
881 glLinkProgram(m_program);
882 if (!CheckProgram(m_program))
885 glClear(GL_COLOR_BUFFER_BIT);
886 glUseProgram(m_program);
887 glDrawArrays(GL_TRIANGLES, 0, 3);
889 return CheckFB(vec3(0, 1, 0));
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 "}",
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 "}";
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);
944 glGenVertexArrays(1, &m_vertex_array);
945 glBindVertexArray(m_vertex_array);
947 for (int i = 0; i < kCount; ++i)
949 if (!RunIteration(glsl_vs[i], glsl_fs))
956 virtual long Cleanup()
959 glDeleteProgram(m_program);
960 glDeleteBuffers(1, &m_buffer);
961 glDeleteVertexArrays(1, &m_vertex_array);
966 class BasicSyntaxCS : public ShaderStorageBufferObjectBase
971 bool RunIteration(const char* cs)
973 std::stringstream ss;
974 ss << "layout(local_size_x = 3) in;" NL "layout (std430) buffer Result {" NL " int result[3];" NL "};" << cs;
977 glDeleteProgram(m_program);
978 m_program = CreateProgramCS(ss.str());
979 glLinkProgram(m_program);
980 if (!CheckProgram(m_program))
983 glUseProgram(m_program);
984 glDispatchCompute(1, 1, 1);
985 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
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);
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);
1002 memset(m_buffer, 0, sizeof(m_buffer));
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
1012 " result[gl_LocalInvocationIndex] = int(g_input_buffer.indata[gl_LocalInvocationID.x].z);" NL "}",
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
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
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 "}",
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 "}",
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 "}",
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
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
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 "}",
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);
1066 for (int i = 0; i < kCount; ++i)
1068 if (!RunIteration(glsl_cs[i]))
1075 virtual long Cleanup()
1078 glDeleteProgram(m_program);
1079 glDeleteBuffers(2, m_buffer);
1083 //-----------------------------------------------------------------------------
1084 // 1.5 BasicSyntaxSSO
1085 //-----------------------------------------------------------------------------
1086 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1089 GLuint m_vsp, m_fsp;
1091 GLuint m_vertex_array;
1093 bool RunIteration(const char* vs)
1096 glDeleteProgram(m_vsp);
1097 m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1098 if (!CheckProgram(m_vsp))
1101 glClear(GL_COLOR_BUFFER_BIT);
1102 glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1103 glDrawArrays(GL_TRIANGLES, 0, 3);
1105 return CheckFB(vec3(0, 1, 0));
1108 virtual long Setup()
1119 if (!IsVSFSAvailable(1, 0))
1120 return NOT_SUPPORTED;
1121 const int kCount = 8;
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 "}",
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))
1160 glGenProgramPipelines(1, &m_pipeline);
1161 glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
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);
1168 glBindProgramPipeline(m_pipeline);
1170 glGenVertexArrays(1, &m_vertex_array);
1171 glBindVertexArray(m_vertex_array);
1173 for (int i = 0; i < kCount; ++i)
1175 if (!RunIteration(glsl_vs[i]))
1182 virtual long Cleanup()
1184 glDeleteProgramPipelines(1, &m_pipeline);
1185 glDeleteProgram(m_vsp);
1186 glDeleteProgram(m_fsp);
1187 glDeleteBuffers(1, &m_buffer);
1188 glDeleteVertexArrays(1, &m_vertex_array);
1193 //-----------------------------------------------------------------------------
1194 // 1.6.x BasicStdLayoutBase
1195 //-----------------------------------------------------------------------------
1196 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1200 GLuint m_vertex_array;
1202 virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1204 virtual long Setup()
1207 memset(m_buffer, 0, sizeof(m_buffer));
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 "}";
1221 m_program = CreateProgram(glsl_vs, glsl_fs);
1222 glLinkProgram(m_program);
1223 if (!CheckProgram(m_program))
1226 glGenBuffers(2, m_buffer);
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);
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);
1235 glGenVertexArrays(1, &m_vertex_array);
1236 glEnable(GL_RASTERIZER_DISCARD);
1238 glUseProgram(m_program);
1239 glBindVertexArray(m_vertex_array);
1240 glDrawArrays(GL_POINTS, 0, 1);
1242 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1243 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1245 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1250 for (size_t i = 0; i < in_data.size(); ++i)
1252 if (in_data[i] != out_data[i])
1254 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i], in_data[i]);
1258 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1264 virtual long Cleanup()
1266 glDisable(GL_RASTERIZER_DISCARD);
1268 glDeleteProgram(m_program);
1269 glDeleteBuffers(2, m_buffer);
1270 glDeleteVertexArrays(1, &m_vertex_array);
1275 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1280 virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1282 virtual long Setup()
1285 memset(m_buffer, 0, sizeof(m_buffer));
1291 std::vector<GLubyte> in_data;
1292 std::stringstream ss;
1293 ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1295 m_program = CreateProgramCS(ss.str());
1296 glLinkProgram(m_program);
1297 if (!CheckProgram(m_program))
1300 glGenBuffers(2, m_buffer);
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);
1308 glUseProgram(m_program);
1309 glDispatchCompute(1, 1, 1);
1311 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1313 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1319 for (size_t i = 0; i < in_data.size(); ++i)
1321 if (in_data[i] != out_data[i])
1323 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i], in_data[i]);
1330 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1336 virtual long Cleanup()
1339 glDeleteProgram(m_program);
1340 glDeleteBuffers(2, m_buffer);
1345 //-----------------------------------------------------------------------------
1346 // 1.6.1 BasicStd430LayoutCase1
1347 //-----------------------------------------------------------------------------
1348 const char* GetInput430c1(std::vector<GLubyte>& in_data)
1350 in_data.resize(6 * 4);
1351 float* fp = reinterpret_cast<float*>(&in_data[0]);
1352 int* ip = reinterpret_cast<int*>(&in_data[0]);
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 "}";
1367 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1369 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1371 return GetInput430c1(in_data);
1375 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1377 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1379 return GetInput430c1(in_data);
1383 //-----------------------------------------------------------------------------
1384 // 1.6.2 BasicStd430LayoutCase2
1385 //-----------------------------------------------------------------------------
1386 const char* GetInput430c2(std::vector<GLubyte>& in_data)
1388 in_data.resize(17 * 4);
1389 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1414 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1416 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1418 return GetInput430c2(in_data);
1422 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1424 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1426 return GetInput430c2(in_data);
1430 //-----------------------------------------------------------------------------
1431 // 1.6.3 BasicStd430LayoutCase3
1432 //-----------------------------------------------------------------------------
1433 const char* GetInput430c3(std::vector<GLubyte>& in_data)
1435 in_data.resize(16 * 4);
1436 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1459 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1461 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1463 return GetInput430c3(in_data);
1467 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1469 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1471 return GetInput430c3(in_data);
1475 //-----------------------------------------------------------------------------
1476 // 1.6.4 BasicStd430LayoutCase4
1477 //-----------------------------------------------------------------------------
1478 const char* GetInput430c4(std::vector<GLubyte>& in_data)
1480 in_data.resize(17 * 4);
1481 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1505 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1507 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1509 return GetInput430c4(in_data);
1513 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1515 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1517 return GetInput430c4(in_data);
1520 //-----------------------------------------------------------------------------
1521 // 1.6.5 BasicStd430LayoutCase5
1522 //-----------------------------------------------------------------------------
1523 const char* GetInput430c5(std::vector<GLubyte>& in_data)
1525 in_data.resize(8 * 4);
1526 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1541 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1543 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1545 return GetInput430c5(in_data);
1549 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1551 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1553 return GetInput430c5(in_data);
1557 //-----------------------------------------------------------------------------
1558 // 1.6.6 BasicStd430LayoutCase6
1559 //-----------------------------------------------------------------------------
1560 const char* GetInput430c6(std::vector<GLubyte>& in_data)
1562 in_data.resize(92 * 4);
1563 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1674 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1676 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1678 return GetInput430c6(in_data);
1682 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1684 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1686 return GetInput430c6(in_data);
1690 //-----------------------------------------------------------------------------
1691 // 1.6.7 BasicStd430LayoutCase7
1692 //-----------------------------------------------------------------------------
1693 const char* GetInput430c7(std::vector<GLubyte>& in_data)
1695 in_data.resize(36 * 4);
1696 int* ip = reinterpret_cast<int*>(&in_data[0]);
1697 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1753 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1755 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1757 return GetInput430c7(in_data);
1761 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1763 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1765 return GetInput430c7(in_data);
1769 //-----------------------------------------------------------------------------
1770 // 1.7.1 BasicStd140LayoutCase1
1771 //-----------------------------------------------------------------------------
1772 const char* GetInput140c1(std::vector<GLubyte>& in_data)
1774 in_data.resize(5 * 4);
1775 float* fp = reinterpret_cast<float*>(&in_data[0]);
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
1785 " for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1788 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1790 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1792 return GetInput140c1(in_data);
1796 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1798 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1800 return GetInput140c1(in_data);
1804 //-----------------------------------------------------------------------------
1805 // 1.7.2 BasicStd140LayoutCase2
1806 //-----------------------------------------------------------------------------
1807 const char* GetInput140c2(std::vector<GLubyte>& in_data)
1809 in_data.resize(18 * 4);
1810 float* fp = reinterpret_cast<float*>(&in_data[0]);
1811 int* ip = reinterpret_cast<int*>(&in_data[0]);
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 "}";
1839 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1841 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1843 return GetInput140c2(in_data);
1847 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1849 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1851 return GetInput140c2(in_data);
1855 //-----------------------------------------------------------------------------
1856 // 1.7.3 BasicStd140LayoutCase3
1857 //-----------------------------------------------------------------------------
1858 const char* GetInput140c3(std::vector<GLubyte>& in_data)
1860 in_data.resize(29 * 4);
1861 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1902 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1904 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1906 return GetInput140c3(in_data);
1910 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1912 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1914 return GetInput140c3(in_data);
1918 //-----------------------------------------------------------------------------
1919 // 1.7.4 BasicStd140LayoutCase4
1920 //-----------------------------------------------------------------------------
1921 const char* GetInput140c4(std::vector<GLubyte>& in_data)
1923 in_data.resize(25 * 4);
1924 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1958 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
1960 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1962 return GetInput140c4(in_data);
1966 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
1968 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1970 return GetInput140c4(in_data);
1974 //-----------------------------------------------------------------------------
1975 // 1.7.5 BasicStd140LayoutCase5
1976 //-----------------------------------------------------------------------------
1977 const char* GetInput140c5(std::vector<GLubyte>& in_data)
1979 in_data.resize(8 * 4);
1980 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
1994 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
1996 virtual const char* GetInput(std::vector<GLubyte>& in_data)
1998 return GetInput140c5(in_data);
2002 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2004 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2006 return GetInput140c5(in_data);
2010 //-----------------------------------------------------------------------------
2011 // 1.7.6 BasicStd140LayoutCase6
2012 //-----------------------------------------------------------------------------
2013 const char* GetInput140c6(std::vector<GLubyte>& in_data)
2015 in_data.resize(96 * 4);
2016 float* fp = reinterpret_cast<float*>(&in_data[0]);
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 "}";
2127 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2129 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2131 return GetInput140c6(in_data);
2135 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2137 virtual const char* GetInput(std::vector<GLubyte>& in_data)
2139 return GetInput140c6(in_data);
2143 //-----------------------------------------------------------------------------
2144 // 1.8.1 BasicAtomicCase1
2145 //-----------------------------------------------------------------------------
2146 class BasicAtomicCase1VSFS : public ShaderStorageBufferObjectBase
2149 GLuint m_storage_buffer[4];
2150 GLuint m_vertex_array;
2151 GLuint m_vertex_buffer;
2153 virtual long Setup()
2156 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2158 m_vertex_buffer = 0;
2164 if (!IsVSFSAvailable(2, 2))
2165 return NOT_SUPPORTED;
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 "}";
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
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))
2228 glGenBuffers(4, m_storage_buffer);
2229 for (GLuint i = 0; i < 4; ++i)
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);
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);
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);
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);
2258 glBindVertexArray(m_vertex_array);
2259 glDrawArrays(GL_POINTS, 0, 4);
2260 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2262 for (int ii = 0; ii < 2; ++ii)
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);
2270 for (GLuint i = 0; i < 4; ++i)
2274 Output("uData at index %d is %d should be %d.\n", i, data[i], 7);
2278 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
2286 for (GLint i = 0; i < 4; ++i)
2290 Output("iData at index %d is %d should be %d.\n", i, data[i], 7);
2294 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2300 virtual long Cleanup()
2303 glDeleteProgram(m_program);
2304 glDeleteBuffers(4, m_storage_buffer);
2305 glDeleteBuffers(1, &m_vertex_buffer);
2306 glDeleteVertexArrays(1, &m_vertex_array);
2310 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2313 GLuint m_storage_buffer[2];
2315 virtual long Setup()
2318 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
2353 glGenBuffers(2, m_storage_buffer);
2354 for (GLuint i = 0; i < 2; ++i)
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);
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);
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);
2373 for (GLuint i = 0; i < 4; ++i)
2377 Output("uData at index %d is %d should be %d.\n", i, data[i], 7);
2381 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
2389 for (GLint i = 0; i < 4; ++i)
2393 Output("iData at index %d is %d should be %d.\n", i, data[i], 7);
2397 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2402 virtual long Cleanup()
2405 glDeleteProgram(m_program);
2406 glDeleteBuffers(2, m_storage_buffer);
2410 //-----------------------------------------------------------------------------
2411 // 1.8.3 BasicAtomicCase3
2412 //-----------------------------------------------------------------------------
2413 class BasicAtomicCase3VSFS : public ShaderStorageBufferObjectBase
2416 GLuint m_storage_buffer;
2417 GLuint m_vertex_array;
2418 GLuint m_vertex_buffer;
2420 virtual long Setup()
2423 m_storage_buffer = 0;
2425 m_vertex_buffer = 0;
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))
2451 /* init storage buffer */
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));
2460 for (int i = 0; i < 4; ++i)
2462 ptr[i * 2] = ivec4(0, 1, 2, 0);
2463 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2465 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2468 /* init vertex buffer */
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);
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);
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);
2491 GLuint* u = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2496 Output("Data at offset 0 is %d should be %d.\n", *u, 16);
2499 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2500 GLint* i = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2505 Output("Data at offset 0 is %d should be %d.\n", *i, 16);
2508 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2513 virtual long Cleanup()
2516 glDeleteProgram(m_program);
2517 glDeleteBuffers(1, &m_storage_buffer);
2518 glDeleteBuffers(1, &m_vertex_buffer);
2519 glDeleteVertexArrays(1, &m_vertex_array);
2523 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2526 GLuint m_storage_buffer;
2528 virtual long Setup()
2531 m_storage_buffer = 0;
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))
2549 /* init storage buffer */
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));
2558 for (int i = 0; i < 4; ++i)
2560 ptr[i * 2] = ivec4(0, 1, 2, 0);
2561 ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2563 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2566 glUseProgram(m_program);
2567 glDispatchCompute(1, 1, 1);
2568 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2570 GLuint* u = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2575 Output("Data at offset 0 is %d should be %d.\n", *u, 16);
2578 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2579 GLint* i = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2584 Output("Data at offset 0 is %d should be %d.\n", *i, 16);
2587 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2592 virtual long Cleanup()
2595 glDeleteProgram(m_program);
2596 glDeleteBuffers(1, &m_storage_buffer);
2601 //-----------------------------------------------------------------------------
2602 // 1.8.4 BasicAtomicCase4
2603 //-----------------------------------------------------------------------------
2604 class BasicAtomicCase4VSFS : public ShaderStorageBufferObjectBase
2607 GLuint m_storage_buffer[2];
2608 GLuint m_vertex_array;
2609 GLuint m_vertex_buffer;
2611 virtual long Setup()
2614 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2616 m_vertex_buffer = 0;
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))
2644 glGenBuffers(2, m_storage_buffer);
2645 /* counter buffer */
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));
2654 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2658 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2659 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
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);
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);
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);
2684 GLuint* udata = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2687 for (GLuint i = 0; i < 8; ++i)
2691 Output("uData at index %d is %d should be %d.\n", i, udata[i], i);
2695 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2696 GLint* idata = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2699 for (GLint i = 0; i < 8; ++i)
2703 Output("iData at index %d is %d should be %d.\n", i, idata[i], i);
2707 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2711 virtual long Cleanup()
2714 glDeleteProgram(m_program);
2715 glDeleteBuffers(2, m_storage_buffer);
2716 glDeleteBuffers(1, &m_vertex_buffer);
2717 glDeleteVertexArrays(1, &m_vertex_array);
2722 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2725 GLuint m_storage_buffer[2];
2727 virtual long Setup()
2730 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
2748 glGenBuffers(2, m_storage_buffer);
2749 /* counter buffer */
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));
2758 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2762 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2763 glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2765 glUseProgram(m_program);
2766 glDispatchCompute(1, 1, 1);
2767 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2769 GLuint* udata = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
2772 for (GLuint i = 0; i < 8; ++i)
2776 Output("uData at index %d is %d should be %d.\n", i, udata[i], i);
2780 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2781 GLint* idata = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
2784 for (GLint i = 0; i < 8; ++i)
2788 Output("iData at index %d is %d should be %d.\n", i, idata[i], i);
2792 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2796 virtual long Cleanup()
2799 glDeleteProgram(m_program);
2800 glDeleteBuffers(2, m_storage_buffer);
2804 //-----------------------------------------------------------------------------
2805 // 1.9.x BasicStdLayoutBase2
2806 //-----------------------------------------------------------------------------
2807 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
2811 GLuint m_vertex_array;
2813 virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2815 virtual long Setup()
2818 memset(m_buffer, 0, sizeof(m_buffer));
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 "}";
2832 m_program = CreateProgram(glsl_vs, glsl_fs);
2833 glLinkProgram(m_program);
2834 if (!CheckProgram(m_program))
2837 glGenBuffers(8, m_buffer);
2839 for (GLuint i = 0; i < 4; ++i)
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);
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);
2849 glGenVertexArrays(1, &m_vertex_array);
2850 glEnable(GL_RASTERIZER_DISCARD);
2852 glUseProgram(m_program);
2853 glBindVertexArray(m_vertex_array);
2854 glDrawArrays(GL_POINTS, 0, 1);
2857 for (int j = 0; j < 4; ++j)
2859 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2860 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2862 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
2866 for (size_t i = 0; i < in_data[j].size(); ++i)
2868 if (in_data[j][i] != out_data[i])
2870 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i],
2875 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2882 virtual long Cleanup()
2884 glDisable(GL_RASTERIZER_DISCARD);
2886 glDeleteProgram(m_program);
2887 glDeleteBuffers(8, m_buffer);
2888 glDeleteVertexArrays(1, &m_vertex_array);
2893 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
2898 virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2900 virtual long Setup()
2903 memset(m_buffer, 0, sizeof(m_buffer));
2909 std::vector<GLubyte> in_data[4];
2910 std::stringstream ss;
2912 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
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))
2921 glGenBuffers(8, m_buffer);
2923 for (GLuint i = 0; i < 4; ++i)
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);
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);
2933 glUseProgram(m_program);
2934 glDispatchCompute(1, 1, 1);
2935 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2938 for (int j = 0; j < 4; ++j)
2940 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
2942 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
2946 for (size_t i = 0; i < in_data[j].size(); ++i)
2948 if (in_data[j][i] != out_data[i])
2950 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i],
2955 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2962 virtual long Cleanup()
2965 glDeleteProgram(m_program);
2966 glDeleteBuffers(8, m_buffer);
2971 //-----------------------------------------------------------------------------
2972 // 1.9.1 BasicStdLayoutCase1
2973 //-----------------------------------------------------------------------------
2974 const char* GetInputC1(std::vector<GLubyte> in_data[4])
2976 for (int i = 0; i < 4; ++i)
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;
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 "}";
2989 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
2991 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
2993 return GetInputC1(in_data);
2997 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
2999 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3001 return GetInputC1(in_data);
3005 //-----------------------------------------------------------------------------
3006 // 1.9.2 BasicStdLayoutCase2
3007 //-----------------------------------------------------------------------------
3008 const char* GetInputC2(std::vector<GLubyte> in_data[4])
3010 /* input 0, std140 */
3012 in_data[0].resize(12 * 4);
3013 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3027 /* input 1, std430 */
3029 in_data[1].resize(3 * 4);
3030 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3035 /* input 2, std140 */
3037 in_data[2].resize(12 * 4);
3038 float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3052 /* input 3, std430 */
3054 in_data[3].resize(3 * 4);
3055 float* fp = reinterpret_cast<float*>(&in_data[3][0]);
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
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 "}";
3075 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3077 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3079 return GetInputC2(in_data);
3083 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3085 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3087 return GetInputC2(in_data);
3091 //-----------------------------------------------------------------------------
3092 // 1.9.3 BasicStdLayoutCase3
3093 //-----------------------------------------------------------------------------
3094 const char* GetInputC3(std::vector<GLubyte> in_data[4])
3096 /* input 0, std140 */
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]);
3158 /* input 1, std430 */
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]);
3183 /* input 2, std140 */
3185 in_data[2].resize(5 * 4);
3186 int* ip = reinterpret_cast<int*>(&in_data[2][0]);
3193 /* input 3, std430 */
3195 in_data[3].resize(2 * 4);
3196 int* ip = reinterpret_cast<int*>(&in_data[3][0]);
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
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;"
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;"
3240 NL " g_output2.data0 = g_input2.data0;" NL " g_output2.data1 = g_input2.data1;"
3242 NL " g_output3.data0 = g_input3.data0;" NL " g_output3.data1 = g_input3.data1;" NL "}";
3245 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3247 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3249 return GetInputC3(in_data);
3253 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3255 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3257 return GetInputC3(in_data);
3261 //-----------------------------------------------------------------------------
3262 // 1.9.4 BasicStdLayoutCase4
3263 //-----------------------------------------------------------------------------
3264 const char* GetInputC4(std::vector<GLubyte> in_data[4])
3266 /* input 0, std140 */
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]);
3329 /* input 1, std140 */
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]);
3392 /* input 2, std430 */
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]);
3443 /* input 3, std430 */
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]);
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];"
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 "}";
3541 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3543 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3545 return GetInputC4(in_data);
3549 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3551 virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3553 return GetInputC4(in_data);
3557 //-----------------------------------------------------------------------------
3558 // 1.10.x BasicOperationsBase
3559 //-----------------------------------------------------------------------------
3560 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3564 GLuint m_vertex_array;
3566 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3568 virtual long Setup()
3571 memset(m_buffer, 0, sizeof(m_buffer));
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 "}";
3586 m_program = CreateProgram(glsl_vs, glsl_fs);
3587 glLinkProgram(m_program);
3588 if (!CheckProgram(m_program))
3591 glGenBuffers(2, m_buffer);
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);
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);
3603 glGenVertexArrays(1, &m_vertex_array);
3604 glEnable(GL_RASTERIZER_DISCARD);
3606 glUseProgram(m_program);
3607 glBindVertexArray(m_vertex_array);
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);
3613 glDrawArrays(GL_POINTS, 0, 1);
3615 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3616 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3618 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3623 for (size_t i = 0; i < expected_data.size(); ++i)
3625 if (expected_data[i] != out_data[i])
3627 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i], expected_data[i]);
3631 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3637 virtual long Cleanup()
3639 glDisable(GL_RASTERIZER_DISCARD);
3641 glDeleteProgram(m_program);
3642 glDeleteBuffers(2, m_buffer);
3643 glDeleteVertexArrays(1, &m_vertex_array);
3648 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3653 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3655 virtual long Setup()
3658 memset(m_buffer, 0, sizeof(m_buffer));
3664 std::vector<GLubyte> in_data;
3665 std::vector<GLubyte> expected_data;
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))
3674 glGenBuffers(2, m_buffer);
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);
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);
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);
3692 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3693 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3695 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3700 for (size_t i = 0; i < expected_data.size(); ++i)
3702 if (expected_data[i] != out_data[i])
3704 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i], expected_data[i]);
3708 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3714 virtual long Cleanup()
3717 glDeleteProgram(m_program);
3718 glDeleteBuffers(2, m_buffer);
3723 //-----------------------------------------------------------------------------
3724 // 1.10.1 BasicOperationsCase1
3725 //-----------------------------------------------------------------------------
3726 const char* GetInputOp1(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3730 in_data.resize(16 * 9);
3731 int* ip = reinterpret_cast<int*>(&in_data[0]);
3732 float* fp = reinterpret_cast<float*>(&in_data[0]);
3740 fp[7] = 0.0f; // data1
3744 ip[11] = 4; // data2
3748 ip[15] = 4; // data3
3752 fp[19] = 4.0f; // data4
3756 fp[23] = 4.0f; // data5
3760 fp[27] = 4.0f; // data5
3764 fp[31] = 4.0f; // data5
3768 fp[35] = 4.0f; // data5
3770 /* expected output */
3772 out_data.resize(16 * 9);
3773 int* ip = reinterpret_cast<int*>(&out_data[0]);
3774 float* fp = reinterpret_cast<float*>(&out_data[0]);
3798 fp[23] = 1.0f; // data5
3802 fp[27] = 1.0f; // data5
3806 fp[31] = 2.0f; // data5
3810 fp[35] = 1.0f; // data5
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 "}";
3829 class BasicOperationsCase1VS : public BasicOperationsBaseVS
3831 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3833 return GetInputOp1(in_data, out_data);
3837 class BasicOperationsCase1CS : public BasicOperationsBaseCS
3839 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3841 return GetInputOp1(in_data, out_data);
3845 //-----------------------------------------------------------------------------
3846 // 1.10.2 BasicOperationsCase2
3847 //-----------------------------------------------------------------------------
3848 const char* GetInputOp2(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3852 in_data.resize(16 * 8);
3853 float* fp = reinterpret_cast<float*>(&in_data[0]);
3888 /* expected output */
3890 out_data.resize(16 * 5);
3891 float* fp = reinterpret_cast<float*>(&out_data[0]);
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 "}";
3921 class BasicOperationsCase2VS : public BasicOperationsBaseVS
3923 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3925 return GetInputOp2(in_data, out_data);
3929 class BasicOperationsCase2CS : public BasicOperationsBaseCS
3931 virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3933 return GetInputOp2(in_data, out_data);
3937 //-----------------------------------------------------------------------------
3938 // 1.11.x BasicStdLayoutBase3
3939 //-----------------------------------------------------------------------------
3940 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
3944 GLuint m_vertex_array;
3946 virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
3948 virtual long Setup()
3951 memset(m_buffer, 0, sizeof(m_buffer));
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 "}";
3965 m_program = CreateProgram(glsl_vs, glsl_fs);
3966 glLinkProgram(m_program);
3967 if (!CheckProgram(m_program))
3970 glGenBuffers(4, m_buffer);
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);
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);
3979 /* output buffer 0 */
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);
3985 /* output buffer 1 */
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);
3992 glGenVertexArrays(1, &m_vertex_array);
3993 glEnable(GL_RASTERIZER_DISCARD);
3995 glUseProgram(m_program);
3996 glBindVertexArray(m_vertex_array);
3998 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4000 glDrawArrays(GL_POINTS, 0, 1);
4003 for (int j = 0; j < 2; ++j)
4005 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4006 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4008 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
4012 for (size_t i = 0; i < in_data[j].size(); ++i)
4014 if (in_data[j][i] != out_data[i])
4016 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i],
4021 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4028 virtual long Cleanup()
4030 glDisable(GL_RASTERIZER_DISCARD);
4032 glDeleteProgram(m_program);
4033 glDeleteBuffers(4, m_buffer);
4034 glDeleteVertexArrays(1, &m_vertex_array);
4039 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4044 virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
4046 virtual long Setup()
4049 memset(m_buffer, 0, sizeof(m_buffer));
4055 std::vector<GLubyte> in_data[2];
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))
4064 glGenBuffers(4, m_buffer);
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);
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);
4073 /* output buffer 0 */
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);
4079 /* output buffer 1 */
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);
4086 glUseProgram(m_program);
4087 glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4088 glDispatchCompute(1, 1, 1);
4091 for (int j = 0; j < 2; ++j)
4093 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4094 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4096 (GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
4100 for (size_t i = 0; i < in_data[j].size(); ++i)
4102 if (in_data[j][i] != out_data[i])
4104 Output("Byte at index %3d is %2x should be %2x.\n", static_cast<int>(i), out_data[i],
4109 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4116 virtual long Cleanup()
4119 glDeleteProgram(m_program);
4120 glDeleteBuffers(4, m_buffer);
4125 //-----------------------------------------------------------------------------
4126 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4127 //-----------------------------------------------------------------------------
4128 const char* GetInputUBO1(std::vector<GLubyte> in_data[2])
4132 in_data[0].resize(12 * 4);
4133 float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4149 in_data[1].resize(3 * 4);
4150 float* fp = reinterpret_cast<float*>(&in_data[1][0]);
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
4169 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4171 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4173 return GetInputUBO1(in_data);
4177 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4179 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4181 return GetInputUBO1(in_data);
4185 //-----------------------------------------------------------------------------
4186 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4187 //-----------------------------------------------------------------------------
4188 const char* GetInputUBO2(std::vector<GLubyte> in_data[2])
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]);
4210 for (int i = 0; i < 20; ++i)
4212 fp[32 + i * 4] = static_cast<float>(15 + i);
4215 for (int i = 0; i < 20; ++i)
4217 fp[116 + i * 4] = static_cast<float>(150 + i);
4220 for (int i = 0; i < 20; ++i)
4222 fp[200 + i * 4] = static_cast<float>(1500 + i);
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]);
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
4340 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4342 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4344 return GetInputUBO2(in_data);
4348 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4350 virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4352 return GetInputUBO2(in_data);
4356 //-----------------------------------------------------------------------------
4357 // 1.12.x BasicMatrixOperationsBase
4358 //-----------------------------------------------------------------------------
4359 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4363 GLuint m_vertex_array;
4365 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4367 static bool Equal(float a, float b)
4369 return fabsf(a - b) < 0.001f;
4372 virtual long Setup()
4375 memset(m_buffer, 0, sizeof(m_buffer));
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 "}";
4390 m_program = CreateProgram(glsl_vs, glsl_fs);
4391 glLinkProgram(m_program);
4392 if (!CheckProgram(m_program))
4395 glGenBuffers(2, m_buffer);
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],
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);
4408 glGenVertexArrays(1, &m_vertex_array);
4409 glEnable(GL_RASTERIZER_DISCARD);
4411 glUseProgram(m_program);
4412 glBindVertexArray(m_vertex_array);
4413 glDrawArrays(GL_POINTS, 0, 1);
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);
4423 for (size_t i = 0; i < expected.size(); ++i)
4425 if (!Equal(expected[i], out_data[i]))
4427 Output("Float at index %3d is %f should be %f.\n", static_cast<int>(i), out_data[i], expected[i]);
4431 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4437 virtual long Cleanup()
4439 glDisable(GL_RASTERIZER_DISCARD);
4441 glDeleteProgram(m_program);
4442 glDeleteBuffers(2, m_buffer);
4443 glDeleteVertexArrays(1, &m_vertex_array);
4448 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4453 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4455 static bool Equal(float a, float b)
4457 return fabsf(a - b) < 0.001f;
4460 virtual long Setup()
4463 memset(m_buffer, 0, sizeof(m_buffer));
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))
4478 glGenBuffers(2, m_buffer);
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],
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);
4491 glUseProgram(m_program);
4492 glDispatchCompute(1, 1, 1);
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);
4502 for (size_t i = 0; i < expected.size(); ++i)
4504 if (!Equal(expected[i], out_data[i]))
4506 Output("Float at index %3d is %f should be %f.\n", static_cast<int>(i), out_data[i], expected[i]);
4510 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4516 virtual long Cleanup()
4519 glDeleteProgram(m_program);
4520 glDeleteBuffers(2, m_buffer);
4525 //-----------------------------------------------------------------------------
4526 // 1.12.1 BasicMatrixOperationsCase1
4527 //-----------------------------------------------------------------------------
4528 const char* GetInputM1(std::vector<float>& in, std::vector<float>& expected)
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; }";
4549 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4551 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4553 return GetInputM1(in, expected);
4557 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4559 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4561 return GetInputM1(in, expected);
4565 //-----------------------------------------------------------------------------
4566 // 1.12.2 BasicMatrixOperationsCase2
4567 //-----------------------------------------------------------------------------
4568 const char* GetInputM2(std::vector<float>& in, std::vector<float>& expected)
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; }";
4597 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4599 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4601 return GetInputM2(in, expected);
4605 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4607 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4609 return GetInputM2(in, expected);
4613 //-----------------------------------------------------------------------------
4614 // 1.12.3 BasicMatrixOperationsCase3
4615 //-----------------------------------------------------------------------------
4616 const char* GetInputM3(std::vector<float>& in, std::vector<float>& expected)
4635 expected[0] = 22.0f;
4636 expected[1] = 49.0f;
4637 expected[2] = 28.0f;
4638 expected[3] = 64.0f;
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; }";
4645 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4647 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4649 return GetInputM3(in, expected);
4653 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4655 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4657 return GetInputM3(in, expected);
4661 //-----------------------------------------------------------------------------
4662 // 1.12.4 BasicMatrixOperationsCase4
4663 //-----------------------------------------------------------------------------
4664 const char* GetInputM4(std::vector<float>& in, std::vector<float>& expected)
4668 // column major mat3x2
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; }";
4693 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4695 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4697 return GetInputM4(in, expected);
4701 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4703 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4705 return GetInputM4(in, expected);
4709 //-----------------------------------------------------------------------------
4710 // 1.12.5 BasicMatrixOperationsCase5
4711 //-----------------------------------------------------------------------------
4712 const char* GetInputM5(std::vector<float>& in, std::vector<float>& expected)
4716 // column major mat3x2
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; }";
4740 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4742 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4744 return GetInputM5(in, expected);
4748 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4750 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4752 return GetInputM5(in, expected);
4756 //-----------------------------------------------------------------------------
4757 // 1.12.6 BasicMatrixOperationsCase6
4758 //-----------------------------------------------------------------------------
4759 const char* GetInputM6(std::vector<float>& in, std::vector<float>& expected)
4770 // column major mat2x3
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; }";
4788 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
4790 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4792 return GetInputM6(in, expected);
4796 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
4798 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4800 return GetInputM6(in, expected);
4804 //-----------------------------------------------------------------------------
4805 // 1.12.7 BasicMatrixOperationsCase7
4806 //-----------------------------------------------------------------------------
4807 const char* GetInputM7(std::vector<float>& in, std::vector<float>& expected)
4818 // column major mat2x3
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; }";
4835 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
4837 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4839 return GetInputM7(in, expected);
4843 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
4845 virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4847 return GetInputM7(in, expected);
4851 //-----------------------------------------------------------------------------
4852 // 2.1 AdvancedSwitchBuffers
4853 //-----------------------------------------------------------------------------
4854 class AdvancedSwitchBuffersVS : public ShaderStorageBufferObjectBase
4856 virtual std::string PassCriteria()
4858 return NL "Everything works as expected.";
4862 GLuint m_storage_buffer[5];
4863 GLuint m_vertex_array;
4866 virtual long Setup()
4869 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
4871 glGenFramebuffers(1, &m_fbo);
4872 glGenTextures(1, &m_rt);
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))
4892 glGenBuffers(5, m_storage_buffer);
4894 /* left, bottom, red quad */
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);
4903 /* right, bottom, green quad */
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);
4912 /* left, top, blue quad */
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);
4921 /* right, top, yellow quad */
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);
4931 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
4932 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
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);
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);
4954 glGenVertexArrays(1, &m_vertex_array);
4956 glUseProgram(m_program);
4957 glBindVertexArray(m_vertex_array);
4959 glClear(GL_COLOR_BUFFER_BIT);
4960 for (int i = 0; i < 4; ++i)
4962 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
4963 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4965 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
4970 glClear(GL_COLOR_BUFFER_BIT);
4971 for (int i = 0; i < 4; ++i)
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);
4977 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
4985 virtual long Cleanup()
4987 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
4997 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5000 GLuint m_storage_buffer[6];
5002 virtual long Setup()
5005 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
5024 glGenBuffers(6, m_storage_buffer);
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);
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);
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));
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);
5058 glUseProgram(m_program);
5059 for (int i = 0; i < 4; ++i)
5061 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5062 glDispatchCompute(1, 1, 1);
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);
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])
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]);
5077 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5078 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5080 for (int i = 0; i < 4; ++i)
5082 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5083 glDispatchCompute(1, 1, 1);
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);
5090 if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5091 out_data[3] != expected[3])
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]);
5101 virtual long Cleanup()
5104 glDeleteProgram(m_program);
5105 glDeleteBuffers(6, m_storage_buffer);
5109 //-----------------------------------------------------------------------------
5110 // 2.2 AdvancedSwitchPrograms
5111 //-----------------------------------------------------------------------------
5112 class AdvancedSwitchProgramsVS : public ShaderStorageBufferObjectBase
5114 GLuint m_program[4];
5115 GLuint m_storage_buffer[4];
5116 GLuint m_vertex_array;
5119 std::string GenSource(int binding)
5121 std::stringstream ss;
5122 ss << NL "struct VertexData {" NL " vec2 position;" NL " vec3 color;" NL "};" NL "layout(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 "}";
5130 virtual long Setup()
5132 memset(m_program, 0, sizeof(m_program));
5133 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5135 glGenFramebuffers(1, &m_fbo);
5136 glGenTextures(1, &m_rt);
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)
5148 m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5149 glLinkProgram(m_program[i]);
5150 if (!CheckProgram(m_program[i]))
5154 glGenBuffers(4, m_storage_buffer);
5156 /* left, bottom, red quad */
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);
5165 /* right, bottom, green quad */
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);
5174 /* left, top, blue quad */
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);
5183 /* right, top, yellow quad */
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);
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);
5202 glGenVertexArrays(1, &m_vertex_array);
5203 glBindVertexArray(m_vertex_array);
5205 glClear(GL_COLOR_BUFFER_BIT);
5206 for (int i = 0; i < 4; ++i)
5208 glUseProgram(m_program[i]);
5209 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5211 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5219 virtual long Cleanup()
5221 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
5232 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5234 GLuint m_program[4];
5235 GLuint m_storage_buffer[5];
5237 virtual long Setup()
5239 memset(m_program, 0, sizeof(m_program));
5240 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5244 std::string GenSource(int binding)
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 "}";
5260 for (int i = 0; i < 4; ++i)
5262 m_program[i] = CreateProgramCS(GenSource(i + 1));
5263 glLinkProgram(m_program[i]);
5264 if (!CheckProgram(m_program[i]))
5268 glGenBuffers(5, m_storage_buffer);
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);
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);
5287 for (int i = 0; i < 4; ++i)
5289 glUseProgram(m_program[i]);
5290 glDispatchCompute(1, 1, 1);
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);
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])
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]);
5305 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5310 virtual long Cleanup()
5313 for (int i = 0; i < 4; ++i)
5314 glDeleteProgram(m_program[i]);
5315 glDeleteBuffers(5, m_storage_buffer);
5320 //-----------------------------------------------------------------------------
5321 // 2.3.1 AdvancedWriteFragment
5322 //-----------------------------------------------------------------------------
5323 class AdvancedWriteFragmentFS : public ShaderStorageBufferObjectBase
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;
5332 virtual long Setup()
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);
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]))
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]))
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;
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);
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);
5399 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
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);
5410 glGenVertexArrays(1, &m_attribless_vertex_array);
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);
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)))
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);
5438 if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5447 virtual long Cleanup()
5449 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
5463 class AdvancedWriteFragmentCS : public ShaderStorageBufferObjectBase
5465 GLuint m_program[2];
5466 GLuint m_storage_buffer;
5467 GLuint m_counter_buffer;
5468 GLuint m_draw_vertex_array;
5471 virtual long Setup()
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);
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]))
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]))
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);
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);
5528 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
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);
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);
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);
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)))
5567 virtual long Cleanup()
5569 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
5582 //-----------------------------------------------------------------------------
5583 // 2.4.1 AdvancedIndirectAddressingCase1
5584 //-----------------------------------------------------------------------------
5585 class AdvancedIndirectAddressingCase1VS : public ShaderStorageBufferObjectBase
5588 GLuint m_storage_buffer[4];
5589 GLuint m_vertex_array;
5590 GLuint m_vertex_buffer;
5593 virtual long Setup()
5596 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5598 m_vertex_buffer = 0;
5599 glGenFramebuffers(1, &m_fbo);
5600 glGenTextures(1, &m_rt);
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))
5625 glGenBuffers(4, m_storage_buffer);
5627 /* material buffer */
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);
5634 /* material id buffer */
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);
5640 /* transform buffer */
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);
5646 /* transform id buffer */
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);
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);
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);
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);
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)))
5688 /* update material id buffer with BufferSubData */
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);
5695 /* update transform id buffer with BufferData */
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);
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)))
5714 virtual long Cleanup()
5716 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
5728 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
5731 GLuint m_storage_buffer[5];
5733 virtual long Setup()
5736 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
5763 glGenBuffers(5, m_storage_buffer);
5765 /* material buffer */
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);
5772 /* material id buffer */
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);
5778 /* transform buffer */
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);
5784 /* transform id buffer */
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);
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);
5794 glUseProgram(m_program);
5795 glDispatchCompute(4, 1, 1);
5796 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5798 (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
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
5811 for (int i = 0; i < 16; ++i)
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])
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]);
5821 for (int i = 32; i < 32 + 16; ++i)
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)
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]);
5831 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5833 /* update material id buffer with BufferSubData */
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);
5840 /* update transform id buffer with BufferData */
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);
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);
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
5864 for (int i = 0; i < 16; ++i)
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])
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]);
5874 for (int i = 32; i < 32 + 16; ++i)
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)
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]);
5891 virtual long Cleanup()
5894 glDeleteProgram(m_program);
5895 glDeleteBuffers(5, m_storage_buffer);
5899 //-----------------------------------------------------------------------------
5900 // 2.4.2 AdvancedIndirectAddressingCase2
5901 //-----------------------------------------------------------------------------
5902 class AdvancedIndirectAddressingCase2VSFS : public ShaderStorageBufferObjectBase
5905 GLuint m_storage_buffer[8];
5906 GLuint m_vertex_array;
5907 GLuint m_vertex_buffer;
5910 virtual long Setup()
5913 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5915 m_vertex_buffer = 0;
5916 glGenFramebuffers(1, &m_fbo);
5917 glGenTextures(1, &m_rt);
5923 if (!IsVSFSAvailable(4, 4))
5924 return NOT_SUPPORTED;
5926 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
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))
5950 glGenBuffers(8, m_storage_buffer);
5952 /* transform buffers */
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)
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);
5961 /* material buffers */
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 }
5966 for (GLuint i = 0; i < 4; ++i)
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);
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);
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);
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);
5999 glUseProgram(m_program);
6000 glBindVertexArray(m_vertex_array);
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)))
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)))
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)))
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)))
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);
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);
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);
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);
6054 if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6061 virtual long Cleanup()
6063 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
6075 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6078 GLuint m_storage_buffer[5];
6080 virtual long Setup()
6083 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6090 glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6092 return NOT_SUPPORTED;
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))
6107 glGenBuffers(5, m_storage_buffer);
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 }
6113 for (GLuint i = 0; i < 4; ++i)
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);
6119 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6120 glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
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);
6130 const float* expected = &data[1][0];
6131 for (int i = 0; i < 4; ++i)
6133 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6134 out_data[i * 4 + 2] != expected[2])
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]);
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);
6148 expected = &data[3][0];
6149 for (int i = 0; i < 4; ++i)
6151 if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6152 out_data[i * 4 + 2] != expected[2])
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]);
6167 virtual long Cleanup()
6170 glDeleteProgram(m_program);
6171 glDeleteBuffers(5, m_storage_buffer);
6176 //-----------------------------------------------------------------------------
6177 // 2.5.1 AdvancedReadWriteCase1
6178 //-----------------------------------------------------------------------------
6179 class AdvancedReadWriteCase1VSFS : public ShaderStorageBufferObjectBase
6182 GLuint m_storage_buffer;
6183 GLuint m_vertex_array;
6184 GLuint m_vertex_buffer;
6186 virtual long Setup()
6189 m_storage_buffer = 0;
6191 m_vertex_buffer = 0;
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))
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));
6225 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
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);
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)))
6253 ptr = reinterpret_cast<float*>(
6254 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6261 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6263 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6264 if (!CheckFB(vec3(1, 0, 1)))
6272 virtual long Cleanup()
6275 glDeleteProgram(m_program);
6276 glDeleteBuffers(1, &m_storage_buffer);
6277 glDeleteBuffers(1, &m_vertex_buffer);
6278 glDeleteVertexArrays(1, &m_vertex_array);
6282 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6285 GLuint m_storage_buffer;
6287 virtual long Setup()
6290 m_storage_buffer = 0;
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))
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)
6316 data[i * 4] = i + 256;
6317 data[i * 4 + 1] = 0;
6318 data[i * 4 + 2] = 0;
6319 data[i * 4 + 3] = 0;
6321 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
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);
6329 for (int i = 0; i < 128; ++i)
6331 if (out_data[i * 4 + 3] != data[i * 4])
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]);
6338 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6339 for (int i = 0; i < 128; ++i)
6341 data[i * 4] = i + 512;
6342 data[i * 4 + 1] = 0;
6343 data[i * 4 + 2] = 0;
6344 data[i * 4 + 3] = 0;
6346 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
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);
6353 for (int i = 0; i < 128; ++i)
6355 if (out_data[i * 4 + 3] != data[i * 4])
6357 Output("Received: %d, but expected: %d\n", out_data[i * 4 + 3], data[i * 4]);
6367 virtual long Cleanup()
6370 glDeleteProgram(m_program);
6371 glDeleteBuffers(1, &m_storage_buffer);
6375 //-----------------------------------------------------------------------------
6376 // 2.6.1 AdvancedUsageCase1
6377 //-----------------------------------------------------------------------------
6378 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6381 GLuint m_storage_buffer[3];
6382 GLuint m_vertex_array;
6383 GLuint m_vertex_buffer;
6386 virtual long Setup()
6389 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6391 m_vertex_buffer = 0;
6392 glGenFramebuffers(1, &m_fbo);
6393 glGenTextures(1, &m_rt);
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))
6417 glGenBuffers(3, m_storage_buffer);
6419 /* transform buffer */
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);
6426 /* material buffer */
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);
6432 /* material id buffer */
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);
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);
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);
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);
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)))
6489 virtual long Cleanup()
6491 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
6503 //-----------------------------------------------------------------------------
6504 // 2.6.2 AdvancedUsageSync
6505 //-----------------------------------------------------------------------------
6506 class AdvancedUsageSyncVSFS : public ShaderStorageBufferObjectBase
6509 GLuint m_storage_buffer[7];
6510 GLuint m_vertex_array;
6512 virtual long Setup()
6515 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
6553 glGenVertexArrays(1, &m_vertex_array);
6554 glGenBuffers(7, m_storage_buffer);
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);
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);
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);
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);
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);
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);
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);
6599 glUseProgram(m_program);
6600 glBindVertexArray(m_vertex_array);
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);
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);
6614 for (int i = 0; i < 4; ++i)
6616 if (data[i] != ref_data[i])
6618 Output("[Buffer0] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6622 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6631 for (int i = 0; i < 2; ++i)
6633 if (data[i] != ref_data[i])
6635 Output("[Buffer1] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6639 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6648 for (int i = 0; i < 2; ++i)
6650 if (data[i] != ref_data[i])
6652 Output("[Buffer2] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6656 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6665 for (int i = 0; i < 1; ++i)
6667 if (data[i] != ref_data[i])
6669 Output("[Buffer3] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6673 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6682 for (int i = 0; i < 4; ++i)
6684 if (data[i] != ref_data[i])
6686 Output("[Buffer4] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6690 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6699 for (int i = 0; i < 2; ++i)
6701 if (data[i] != ref_data[i])
6703 Output("[Buffer5] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6707 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6716 for (int i = 0; i < 2; ++i)
6718 if (data[i] != ref_data[i])
6720 Output("[Buffer6] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6724 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6730 virtual long Cleanup()
6733 glDeleteProgram(m_program);
6734 glDeleteBuffers(7, m_storage_buffer);
6735 glDeleteVertexArrays(1, &m_vertex_array);
6739 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
6742 GLuint m_storage_buffer[7];
6744 virtual long Setup()
6747 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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))
6780 glGenBuffers(7, m_storage_buffer);
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);
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);
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);
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);
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);
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);
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);
6825 glUseProgram(m_program);
6827 glDispatchCompute(1, 1, 3);
6828 glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6829 glDispatchCompute(1, 1, 3);
6831 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
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);
6840 for (int i = 0; i < 4; ++i)
6842 if (data[i] != ref_data[i])
6844 Output("[Buffer0] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6848 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6857 for (int i = 0; i < 2; ++i)
6859 if (data[i] != ref_data[i])
6861 Output("[Buffer1] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6865 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6874 for (int i = 0; i < 2; ++i)
6876 if (data[i] != ref_data[i])
6878 Output("[Buffer2] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6882 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6891 for (int i = 0; i < 1; ++i)
6893 if (data[i] != ref_data[i])
6895 Output("[Buffer3] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6899 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6908 for (int i = 0; i < 4; ++i)
6910 if (data[i] != ref_data[i])
6912 Output("[Buffer4] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6916 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6925 for (int i = 0; i < 2; ++i)
6927 if (data[i] != ref_data[i])
6929 Output("[Buffer5] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6933 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
6942 for (int i = 0; i < 2; ++i)
6944 if (data[i] != ref_data[i])
6946 Output("[Buffer6] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
6950 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6956 virtual long Cleanup()
6959 glDeleteProgram(m_program);
6960 glDeleteBuffers(7, m_storage_buffer);
6964 //-----------------------------------------------------------------------------
6965 // 2.6.3 AdvancedUsageOperators
6966 //-----------------------------------------------------------------------------
6967 class AdvancedUsageOperatorsVS : public ShaderStorageBufferObjectBase
6970 GLuint m_storage_buffer[2];
6971 GLuint m_vertex_array;
6973 virtual long Setup()
6976 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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 "}";
6995 m_program = CreateProgram(glsl_vs, glsl_fs);
6996 glLinkProgram(m_program);
6997 if (!CheckProgram(m_program))
7000 glGenVertexArrays(1, &m_vertex_array);
7001 glGenBuffers(2, m_storage_buffer);
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);
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);
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);
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);
7029 for (int i = 0; i < 2; ++i)
7031 if (data[i] != ref_data[i])
7033 Output("[Buffer0] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
7037 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
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);
7046 for (int i = 0; i < 1; ++i)
7048 if (data[i] != ref_data[i])
7050 Output("[Buffer1] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
7054 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7060 virtual long Cleanup()
7062 glDisable(GL_RASTERIZER_DISCARD);
7064 glDeleteProgram(m_program);
7065 glDeleteBuffers(2, m_storage_buffer);
7066 glDeleteVertexArrays(1, &m_vertex_array);
7070 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7073 GLuint m_storage_buffer[2];
7075 virtual long Setup()
7078 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
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 "}";
7092 m_program = CreateProgramCS(glsl_cs);
7093 glLinkProgram(m_program);
7094 if (!CheckProgram(m_program))
7097 glGenBuffers(2, m_storage_buffer);
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);
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);
7112 glUseProgram(m_program);
7113 glDispatchCompute(1, 1, 1);
7114 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
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);
7123 for (int i = 0; i < 2; ++i)
7125 if (data[i] != ref_data[i])
7127 Output("[Buffer0] Data at index %d is %d should be %d.\n", i, data[i], ref_data[i]);
7131 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7137 virtual long Cleanup()
7140 glDeleteProgram(m_program);
7141 glDeleteBuffers(2, m_storage_buffer);
7146 //-----------------------------------------------------------------------------
7147 // 2.7 AdvancedUnsizedArrayLength
7148 //-----------------------------------------------------------------------------
7149 template <int stage>
7150 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7153 GLuint m_storage_buffer[4];
7154 GLuint m_vertex_array;
7156 virtual long Setup()
7159 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7164 virtual long Cleanup()
7167 glDeleteProgram(m_program);
7168 glDeleteBuffers(4, m_storage_buffer);
7169 if (stage != compute)
7170 glDeleteVertexArrays(1, &m_vertex_array);
7173 std::string BuildShaderPT(int st)
7175 std::ostringstream os;
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";
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);";
7189 std::string BuildShader()
7191 std::ostringstream os;
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)
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);"
7204 if (stage == fragment)
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;
7209 if (stage == compute)
7211 os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
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)
7225 std::string glsl_vs = BuildShader();
7226 std::string glsl_fs = BuildShaderPT(fragment);
7227 m_program = CreateProgram(glsl_vs, glsl_fs);
7229 else if (stage == fragment)
7231 std::string glsl_vs = BuildShaderPT(vertex);
7232 std::string glsl_fs = BuildShader();
7233 m_program = CreateProgram(glsl_vs, glsl_fs);
7237 std::string glsl_cs = BuildShader();
7238 m_program = CreateProgramCS(glsl_cs);
7240 glLinkProgram(m_program);
7241 if (!CheckProgram(m_program))
7243 glUseProgram(m_program);
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)
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);
7254 if (stage != compute)
7256 glGenVertexArrays(1, &m_vertex_array);
7257 glBindVertexArray(m_vertex_array);
7258 glDrawArrays(GL_POINTS, 0, 1);
7262 glDispatchCompute(1, 1, 1);
7264 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
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);
7271 for (int i = 0; i < kBufs - 1; ++i)
7272 if (dataout[i + 1] != sizes[i])
7274 Output("Array %d length is %d should be %d.\n", i, dataout[i + 1], sizes[i]);
7277 if (dataout[0] != sizes[kBufs - 1] - 1)
7279 Output("Array %d length is %d should be %d.\n", kBufs - 1, dataout[0], sizes[kBufs - 1] - 1);
7282 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7291 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7294 GLuint m_storage_buffer[8];
7295 GLuint m_vertex_array;
7296 virtual void SetPath() = 0;
7298 virtual long Setup()
7301 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7306 virtual long Cleanup()
7309 glDeleteProgram(m_program);
7310 glDeleteBuffers(8, m_storage_buffer);
7311 if (stage != compute)
7312 glDeleteVertexArrays(1, &m_vertex_array);
7315 std::string BuildShaderPT(int stagept)
7317 std::ostringstream os;
7318 if (stagept == vertex)
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";
7323 if (stagept == fragment)
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);";
7331 std::string BuildShader()
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" } };
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 "};";
7346 std::string lo = "";
7347 std::string l[4] = { "std140", "std430", "shared", "packed" };
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 "};";
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)
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);"
7381 if (stage == fragment)
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;
7386 if (stage == compute)
7388 os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7396 const int kSize = 100000;
7397 const int kBufs = 8;
7399 if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7400 return NOT_SUPPORTED;
7402 glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
7404 glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
7405 if (blocksC < kBufs)
7406 return NOT_SUPPORTED;
7407 if (stage == vertex)
7409 std::string glsl_vs = BuildShader();
7410 std::string glsl_fs = BuildShaderPT(fragment);
7411 m_program = CreateProgram(glsl_vs, glsl_fs);
7413 else if (stage == fragment)
7415 std::string glsl_vs = BuildShaderPT(vertex);
7416 std::string glsl_fs = BuildShader();
7417 m_program = CreateProgram(glsl_vs, glsl_fs);
7421 std::string glsl_cs = BuildShader();
7422 m_program = CreateProgramCS(glsl_cs);
7424 glLinkProgram(m_program);
7425 if (!CheckProgram(m_program))
7427 glUseProgram(m_program);
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 } };
7447 std::vector<ivec4> data(kSize, ivec4(41));
7448 for (int i = 0; i < kBufs; ++i)
7450 if (layout == std430)
7452 bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
7453 if (etype == structure)
7455 bufsize[i][1] = 4 * std430struct[i];
7458 else if (layout == std140)
7460 bufsize[i][1] = 4 * columns[etype][i] * 4;
7461 if (etype == structure)
7463 bufsize[i][1] = 4 * std140struct[i];
7468 bufsize[i][1] = 4 * mindw[etype][i];
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);
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)
7482 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7484 else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
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
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
7497 if (stage != compute)
7499 glGenVertexArrays(1, &m_vertex_array);
7500 glBindVertexArray(m_vertex_array);
7501 glDrawArrays(GL_POINTS, 0, 1);
7505 glDispatchCompute(1, 1, 1);
7507 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
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);
7514 for (int i = 0; i < kBufs - 1; ++i)
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])
7522 Output("Array %d length is %d should be %d.\n", i, dataout[i], sizes[i]);
7525 if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
7527 Output("Array %d length is %d should be not greater that %d.\n", i, dataout[i], sizes[i]);
7531 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7533 if (length_as_index)
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);
7539 int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
7540 if (dataout[i] != 82)
7542 Output("Array 4 index %d is %d should be 82.\n", i, dataout[i]);
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);
7550 i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
7551 if (dataout[i] != 82)
7553 Output("Array 6 index %d is %d should be 82.\n", i, dataout[i]);
7556 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7571 bool length_as_index;
7573 AdvancedUnsizedArrayLength2()
7577 , other_members(false)
7578 , bind_seq(bindbasebefore)
7579 , length_as_index(false)
7584 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7587 virtual void SetPath()
7589 length_as_index = true;
7593 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7596 virtual void SetPath()
7598 bind_seq = bindbaseafter;
7602 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7605 virtual void SetPath()
7607 bind_seq = bindrangeoffset;
7611 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7614 virtual void SetPath()
7616 bind_seq = bindrangesize;
7620 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7623 virtual void SetPath()
7629 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7632 virtual void SetPath()
7638 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7641 virtual void SetPath()
7647 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7650 virtual void SetPath()
7656 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7659 virtual void SetPath()
7666 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7669 virtual void SetPath()
7676 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7679 virtual void SetPath()
7686 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7689 virtual void SetPath()
7696 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7699 virtual void SetPath()
7706 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7709 virtual void SetPath()
7716 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7719 virtual void SetPath()
7726 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7729 virtual void SetPath()
7737 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7740 virtual void SetPath()
7745 other_members = true;
7749 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7752 virtual void SetPath()
7760 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7763 virtual void SetPath()
7771 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7774 virtual void SetPath()
7779 other_members = true;
7783 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7786 virtual void SetPath()
7794 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7797 virtual void SetPath()
7805 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7808 virtual void SetPath()
7816 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7819 virtual void SetPath()
7822 other_members = true;
7826 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7829 virtual void SetPath()
7832 other_members = true;
7836 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7839 virtual void SetPath()
7843 other_members = true;
7847 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7850 virtual void SetPath()
7853 other_members = true;
7857 //-----------------------------------------------------------------------------
7858 // 2.8 AdvancedMatrix
7859 //-----------------------------------------------------------------------------
7860 class AdvancedMatrixVSFS : public ShaderStorageBufferObjectBase
7863 GLuint m_storage_buffer[3];
7864 GLuint m_vertex_array;
7865 GLuint m_vertex_buffer;
7868 virtual long Setup()
7871 memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7873 m_vertex_buffer = 0;
7874 glGenFramebuffers(1, &m_fbo);
7875 glGenTextures(1, &m_rt);
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))
7906 glGenBuffers(3, m_storage_buffer);
7908 /* transform buffer */
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,
7915 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7916 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7918 /* transform buffer */
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,
7923 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7924 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
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);
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);
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);
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);
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)))
7966 virtual long Cleanup()
7968 glViewport(0, 0, getWindowWidth(), getWindowHeight());
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);
7980 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
7983 GLuint m_storage_buffer;
7985 virtual long Setup()
7988 m_storage_buffer = 0;
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))
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)
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);
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);
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,
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)
8031 if (out_data[i] != expected[i])
8033 Output("Received: %f, but expected: %f\n", out_data[i], expected[i]);
8037 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8044 virtual long Cleanup()
8047 glDeleteProgram(m_program);
8048 glDeleteBuffers(1, &m_storage_buffer);
8053 //-----------------------------------------------------------------------------
8054 // 4.1.1 NegativeAPIBind
8055 //-----------------------------------------------------------------------------
8056 class NegativeAPIBind : public ShaderStorageBufferObjectBase
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);
8068 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8069 if (glGetError() != GL_INVALID_VALUE)
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");
8077 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8078 if (glGetError() != GL_INVALID_VALUE)
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");
8086 glGenBuffers(1, &buffer);
8087 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, alignment - 1, 0);
8088 if (glGetError() != GL_INVALID_VALUE)
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");
8100 //-----------------------------------------------------------------------------
8101 // 4.2.1 NegativeGLSLCompileTime
8102 //-----------------------------------------------------------------------------
8103 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8105 static std::string Shader1(int binding)
8107 std::stringstream ss;
8108 ss << NL "layout(binding = " << binding
8109 << ") buffer Buffer {" NL " int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}";
8113 static std::string Shader2(int binding)
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 "}";
8125 glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
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 "}"))
8131 // syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8132 if (!Compile(Shader1(-1)))
8134 // invalid value 96 for layout specifier 'binding'
8135 if (!Compile(Shader1(bindings)))
8138 // invalid value 98 for layout specifier 'binding'
8139 if (!Compile(Shader2(bindings - 2)))
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 "}"))
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 "}"))
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 "}"))
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
8160 // unknown layout specifier 'std430'
8161 if (!Compile(NL "buffer SSBO {" NL " layout(std430) int x;" NL "};" NL "void main() {" NL " x = 0;" NL "}"))
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
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 "}"))
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 "}"))
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 "}"))
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 "}"))
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 "}"))
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);" //
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 "}"))
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 "}"))
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 "}"))
8219 bool Compile(const std::string& source)
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);
8228 glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8229 Output("Shader Info Log:\n%s\n", log);
8232 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8235 if (status == GL_TRUE)
8237 Output("Compilation should fail.\n");
8245 //-----------------------------------------------------------------------------
8246 // 4.2.2 NegativeGLSLLinkTime
8247 //-----------------------------------------------------------------------------
8248 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
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 "}"))
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
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
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 "}"))
8276 bool Link(const std::string& cs0, const std::string& cs1)
8278 const GLuint p = glCreateProgram();
8282 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8283 glAttachShader(p, sh);
8285 const char* const src = cs0.c_str();
8286 glShaderSource(sh, 1, &src, NULL);
8287 glCompileShader(sh);
8290 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8291 if (status == GL_FALSE)
8293 Output("VS compilation should be ok.\n");
8301 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8302 glAttachShader(p, sh);
8304 const char* const src = cs1.c_str();
8305 glShaderSource(sh, 1, &src, NULL);
8306 glCompileShader(sh);
8309 glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8310 if (status == GL_FALSE)
8312 Output("FS compilation should be ok.\n");
8322 glGetProgramInfoLog(p, sizeof(log), NULL, log);
8323 Output("Program Info Log:\n%s\n", log);
8326 glGetProgramiv(p, GL_LINK_STATUS, &status);
8329 if (status == GL_TRUE)
8331 Output("Link operation should fail.\n");
8338 } // anonymous namespace
8340 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
8341 : TestCaseGroup(context, "shader_storage_buffer_object", "")
8345 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8349 void ShaderStorageBufferObjectTests::init()
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>));
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>));
8515 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
8516 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
8518 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
8519 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
8521 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
8522 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
8524 addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
8525 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
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>));
8534 } // namespace es31compatibility
8535 } // namespace gl4cts