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