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
32namespace gl4cts
33{
34
35namespace es31compatibility
36{
37using namespace glw;
38
39namespace
40{
41
42typedef tcu::Vec2  vec2;
43typedef tcu::Vec3  vec3;
44typedef tcu::Vec4  vec4;
45typedef tcu::IVec4 ivec4;
46typedef tcu::UVec4 uvec4;
47typedef tcu::Mat4  mat4;
48
49enum ShaderStage
50{
51	vertex,
52	fragment,
53	compute
54};
55enum BufferLayout
56{
57	std140,
58	std430,
59	shared,
60	packed
61};
62enum ElementType
63{
64	vector,
65	matrix_cm,
66	matrix_rm,
67	structure
68};
69enum BindingSeq
70{
71	bindbasebefore,
72	bindbaseafter,
73	bindrangeoffset,
74	bindrangesize
75};
76
77const char* const kGLSLVer = "#version 310 es" NL "precision highp float;" NL "precision highp int;";
78
79class 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
101public:
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//-----------------------------------------------------------------------------
486class 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
546class 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//-----------------------------------------------------------------------------
597class 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//-----------------------------------------------------------------------------
671class 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//-----------------------------------------------------------------------------
869class 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
965class 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//-----------------------------------------------------------------------------
1085class 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//-----------------------------------------------------------------------------
1195class 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
1276class 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//-----------------------------------------------------------------------------
1351const 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
1370class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1371{
1372	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1373	{
1374		return GetInput430c1(in_data);
1375	}
1376};
1377
1378class 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//-----------------------------------------------------------------------------
1389const 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
1417class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1418{
1419	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1420	{
1421		return GetInput430c2(in_data);
1422	}
1423};
1424
1425class 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//-----------------------------------------------------------------------------
1436const 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
1462class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1463{
1464	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1465	{
1466		return GetInput430c3(in_data);
1467	}
1468};
1469
1470class 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//-----------------------------------------------------------------------------
1481const 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
1508class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1509{
1510	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1511	{
1512		return GetInput430c4(in_data);
1513	}
1514};
1515
1516class 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//-----------------------------------------------------------------------------
1526const 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
1544class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1545{
1546	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1547	{
1548		return GetInput430c5(in_data);
1549	}
1550};
1551
1552class 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//-----------------------------------------------------------------------------
1563const 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
1677class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1678{
1679	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1680	{
1681		return GetInput430c6(in_data);
1682	}
1683};
1684
1685class 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//-----------------------------------------------------------------------------
1696const 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
1756class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1757{
1758	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1759	{
1760		return GetInput430c7(in_data);
1761	}
1762};
1763
1764class 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//-----------------------------------------------------------------------------
1775const 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
1791class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1792{
1793	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1794	{
1795		return GetInput140c1(in_data);
1796	}
1797};
1798
1799class 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//-----------------------------------------------------------------------------
1810const 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
1842class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1843{
1844	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1845	{
1846		return GetInput140c2(in_data);
1847	}
1848};
1849
1850class 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//-----------------------------------------------------------------------------
1861const 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
1905class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1906{
1907	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1908	{
1909		return GetInput140c3(in_data);
1910	}
1911};
1912
1913class 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//-----------------------------------------------------------------------------
1924const 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
1961class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
1962{
1963	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1964	{
1965		return GetInput140c4(in_data);
1966	}
1967};
1968
1969class 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//-----------------------------------------------------------------------------
1980const 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
1997class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
1998{
1999	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2000	{
2001		return GetInput140c5(in_data);
2002	}
2003};
2004
2005class 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//-----------------------------------------------------------------------------
2016const 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
2130class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2131{
2132	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2133	{
2134		return GetInput140c6(in_data);
2135	}
2136};
2137
2138class 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//-----------------------------------------------------------------------------
2149class 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};
2315class 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//-----------------------------------------------------------------------------
2420class 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};
2532class 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//-----------------------------------------------------------------------------
2615class 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
2735class 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//-----------------------------------------------------------------------------
2822class 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
2910class 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//-----------------------------------------------------------------------------
2993const 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
3008class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3009{
3010	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3011	{
3012		return GetInputC1(in_data);
3013	}
3014};
3015
3016class 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//-----------------------------------------------------------------------------
3027const 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
3094class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3095{
3096	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3097	{
3098		return GetInputC2(in_data);
3099	}
3100};
3101
3102class 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//-----------------------------------------------------------------------------
3113const 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
3264class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3265{
3266	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3267	{
3268		return GetInputC3(in_data);
3269	}
3270};
3271
3272class 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//-----------------------------------------------------------------------------
3283const 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
3560class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3561{
3562	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3563	{
3564		return GetInputC4(in_data);
3565	}
3566};
3567
3568class 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//-----------------------------------------------------------------------------
3579class 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
3669class 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//-----------------------------------------------------------------------------
3749const 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
3852class 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
3860class 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//-----------------------------------------------------------------------------
3871const 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
3944class 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
3952class 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//-----------------------------------------------------------------------------
3963class 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
4064class 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//-----------------------------------------------------------------------------
4155const 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
4196class 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
4204class 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//-----------------------------------------------------------------------------
4215const 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
4367class 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
4375class 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//-----------------------------------------------------------------------------
4386class 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
4477class 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//-----------------------------------------------------------------------------
4559const 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
4580class 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
4588class 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//-----------------------------------------------------------------------------
4599const 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
4628class 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
4636class 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//-----------------------------------------------------------------------------
4647const 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
4676class 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
4684class 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//-----------------------------------------------------------------------------
4695const 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
4724class 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
4732class 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//-----------------------------------------------------------------------------
4743const 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
4771class 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
4779class 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//-----------------------------------------------------------------------------
4790const 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
4819class 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
4827class 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//-----------------------------------------------------------------------------
4838const 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
4866class 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
4874class 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//-----------------------------------------------------------------------------
4885class 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};
5028class 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//-----------------------------------------------------------------------------
5149class 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};
5269class 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//-----------------------------------------------------------------------------
5363class 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
5503class 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//-----------------------------------------------------------------------------
5625class 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
5768class 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//-----------------------------------------------------------------------------
5950class 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
6123class 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//-----------------------------------------------------------------------------
6231class 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};
6334class 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//-----------------------------------------------------------------------------
6433class 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//-----------------------------------------------------------------------------
6561class 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};
6808class 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//-----------------------------------------------------------------------------
7050class 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};
7157class 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//-----------------------------------------------------------------------------
7238template <int stage>
7239class 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
7384class 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
7664public:
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
7683class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7684{
7685public:
7686	virtual void SetPath()
7687	{
7688		length_as_index = true;
7689	}
7690};
7691
7692class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7693{
7694public:
7695	virtual void SetPath()
7696	{
7697		bind_seq = bindbaseafter;
7698	}
7699};
7700
7701class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7702{
7703public:
7704	virtual void SetPath()
7705	{
7706		bind_seq = bindrangeoffset;
7707	}
7708};
7709
7710class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7711{
7712public:
7713	virtual void SetPath()
7714	{
7715		bind_seq = bindrangesize;
7716	}
7717};
7718
7719class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7720{
7721public:
7722	virtual void SetPath()
7723	{
7724		etype = vector;
7725	}
7726};
7727
7728class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7729{
7730public:
7731	virtual void SetPath()
7732	{
7733		etype = matrix_cm;
7734	}
7735};
7736
7737class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7738{
7739public:
7740	virtual void SetPath()
7741	{
7742		etype = matrix_rm;
7743	}
7744};
7745
7746class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7747{
7748public:
7749	virtual void SetPath()
7750	{
7751		etype = structure;
7752	}
7753};
7754
7755class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7756{
7757public:
7758	virtual void SetPath()
7759	{
7760		stage  = compute;
7761		layout = std140;
7762	}
7763};
7764
7765class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7766{
7767public:
7768	virtual void SetPath()
7769	{
7770		etype  = matrix_cm;
7771		layout = std140;
7772	}
7773};
7774
7775class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7776{
7777public:
7778	virtual void SetPath()
7779	{
7780		etype  = matrix_rm;
7781		layout = std140;
7782	}
7783};
7784
7785class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7786{
7787public:
7788	virtual void SetPath()
7789	{
7790		etype  = structure;
7791		layout = std140;
7792	}
7793};
7794
7795class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7796{
7797public:
7798	virtual void SetPath()
7799	{
7800		etype  = vector;
7801		layout = packed;
7802	}
7803};
7804
7805class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7806{
7807public:
7808	virtual void SetPath()
7809	{
7810		etype  = matrix_cm;
7811		layout = packed;
7812	}
7813};
7814
7815class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7816{
7817public:
7818	virtual void SetPath()
7819	{
7820		etype  = matrix_rm;
7821		layout = shared;
7822	}
7823};
7824
7825class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7826{
7827public:
7828	virtual void SetPath()
7829	{
7830		stage  = fragment;
7831		etype  = vector;
7832		layout = std430;
7833	}
7834};
7835
7836class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7837{
7838public:
7839	virtual void SetPath()
7840	{
7841		stage		  = fragment;
7842		etype		  = matrix_cm;
7843		layout		  = std430;
7844		other_members = true;
7845	}
7846};
7847
7848class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7849{
7850public:
7851	virtual void SetPath()
7852	{
7853		stage  = fragment;
7854		etype  = matrix_rm;
7855		layout = std140;
7856	}
7857};
7858
7859class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7860{
7861public:
7862	virtual void SetPath()
7863	{
7864		stage  = fragment;
7865		etype  = structure;
7866		layout = std140;
7867	}
7868};
7869
7870class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7871{
7872public:
7873	virtual void SetPath()
7874	{
7875		stage		  = vertex;
7876		etype		  = vector;
7877		layout		  = std430;
7878		other_members = true;
7879	}
7880};
7881
7882class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7883{
7884public:
7885	virtual void SetPath()
7886	{
7887		stage  = vertex;
7888		etype  = matrix_cm;
7889		layout = std140;
7890	}
7891};
7892
7893class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7894{
7895public:
7896	virtual void SetPath()
7897	{
7898		stage  = vertex;
7899		etype  = matrix_rm;
7900		layout = packed;
7901	}
7902};
7903
7904class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7905{
7906public:
7907	virtual void SetPath()
7908	{
7909		stage  = vertex;
7910		etype  = structure;
7911		layout = std140;
7912	}
7913};
7914
7915class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7916{
7917public:
7918	virtual void SetPath()
7919	{
7920		etype		  = vector;
7921		other_members = true;
7922	}
7923};
7924
7925class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7926{
7927public:
7928	virtual void SetPath()
7929	{
7930		etype		  = matrix_cm;
7931		other_members = true;
7932	}
7933};
7934
7935class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7936{
7937public:
7938	virtual void SetPath()
7939	{
7940		etype		  = matrix_rm;
7941		layout		  = std140;
7942		other_members = true;
7943	}
7944};
7945
7946class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7947{
7948public:
7949	virtual void SetPath()
7950	{
7951		etype		  = structure;
7952		other_members = true;
7953	}
7954};
7955
7956//-----------------------------------------------------------------------------
7957// 2.8 AdvancedMatrix
7958//-----------------------------------------------------------------------------
7959class 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
8079class 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//-----------------------------------------------------------------------------
8156class 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//-----------------------------------------------------------------------------
8208class 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//-----------------------------------------------------------------------------
8355class 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
8451ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
8452	: TestCaseGroup(context, "shader_storage_buffer_object", "")
8453{
8454}
8455
8456ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8457{
8458}
8459
8460void 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