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]	 = 9.0f;
4230		fp[12]	= 10.0f;
4231		fp[16]	= 11.0f;
4232		fp[20]	= 12.0f;
4233		fp[24]	= 13.0f;
4234
4235		ip[28] = 14;
4236		for (int i = 0; i < 20; ++i)
4237		{
4238			fp[32 + i * 4] = static_cast<float>(15 + i);
4239		}
4240		ip[112] = 140;
4241		for (int i = 0; i < 20; ++i)
4242		{
4243			fp[116 + i * 4] = static_cast<float>(150 + i);
4244		}
4245		ip[196] = 1400;
4246		for (int i = 0; i < 20; ++i)
4247		{
4248			fp[200 + i * 4] = static_cast<float>(1500 + i);
4249		}
4250	}
4251	/* SSBO */
4252	{
4253		in_data[1].resize(76 * 4);
4254		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4255		int*   ip = reinterpret_cast<int*>(&in_data[1][0]);
4256		fp[0]	 = 1.0f;
4257		fp[1]	 = 2.0f;
4258		fp[2]	 = 3.0f;
4259		fp[3]	 = 4.0f;
4260		fp[4]	 = 5.0f;
4261		fp[5]	 = 6.0f;
4262		fp[6]	 = 7.0f;
4263		fp[7]	 = 8.0f;
4264		fp[8]	 = 9.0f;
4265		fp[9]	 = 10.0f;
4266		fp[10]	= 11.0f;
4267		fp[11]	= 12.0f;
4268		fp[12]	= 13.0f;
4269		ip[13]	= 14;
4270		fp[14]	= 15.0f;
4271		fp[15]	= 16.0f;
4272		fp[16]	= 17.0f;
4273		fp[17]	= 18.0f;
4274		fp[18]	= 19.0f;
4275		fp[19]	= 20.0f;
4276		fp[20]	= 21.0f;
4277		fp[21]	= 22.0f;
4278		fp[22]	= 23.0f;
4279		fp[23]	= 24.0f;
4280		fp[24]	= 25.0f;
4281		fp[25]	= 26.0f;
4282		fp[26]	= 27.0f;
4283		fp[27]	= 28.0f;
4284		fp[28]	= 29.0f;
4285		fp[29]	= 30.0f;
4286		fp[30]	= 31.0f;
4287		fp[31]	= 32.0f;
4288		fp[32]	= 33.0f;
4289		fp[33]	= 34.0f;
4290		ip[34]	= 35;
4291		fp[35]	= 36.0f;
4292		fp[36]	= 37.0f;
4293		fp[37]	= 38.0f;
4294		fp[38]	= 39.0f;
4295		fp[39]	= 40.0f;
4296		fp[40]	= 41.0f;
4297		fp[41]	= 42.0f;
4298		fp[42]	= 43.0f;
4299		fp[43]	= 44.0f;
4300		fp[44]	= 45.0f;
4301		fp[45]	= 46.0f;
4302		fp[46]	= 47.0f;
4303		fp[47]	= 48.0f;
4304		fp[48]	= 49.0f;
4305		fp[49]	= 50.0f;
4306		fp[50]	= 51.0f;
4307		fp[51]	= 52.0f;
4308		fp[52]	= 53.0f;
4309		fp[53]	= 54.0f;
4310		fp[54]	= 55.0f;
4311		ip[55]	= 56;
4312		fp[56]	= 57.0f;
4313		fp[57]	= 58.0f;
4314		fp[58]	= 59.0f;
4315		fp[59]	= 60.0f;
4316		fp[60]	= 61.0f;
4317		fp[61]	= 62.0f;
4318		fp[62]	= 63.0f;
4319		fp[63]	= 64.0f;
4320		fp[64]	= 65.0f;
4321		fp[65]	= 66.0f;
4322		fp[66]	= 67.0f;
4323		fp[67]	= 68.0f;
4324		fp[68]	= 69.0f;
4325		fp[69]	= 70.0f;
4326		fp[70]	= 71.0f;
4327		fp[71]	= 72.0f;
4328		fp[72]	= 73.0f;
4329		fp[73]	= 74.0f;
4330		fp[74]	= 75.0f;
4331		fp[75]	= 76.0f;
4332	}
4333	return NL
4334		"struct MM {" NL "  float mm_a[5];" NL "};" NL "struct TT {" NL "  int tt_a;" NL "  MM  tt_b[4];" NL "};" NL
4335		"layout(std140, binding = 0) uniform InputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4336		"  float d[4];" NL "  TT    e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4337		"  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_input_ssbo;" NL
4338		"layout(std140, binding = 1) buffer OutputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4339		"  float d[4];" NL "  TT    e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4340		"  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_output_ssbo;" NL
4341		"uniform int g_index1;" NL "void main() {" NL "  int index0 = 0;" NL NL "  g_output_ubo.a = g_input_ubo.a;" NL
4342		"  g_output_ubo.b = g_input_ubo.b;" NL "  g_output_ubo.c = g_input_ubo.c;" NL
4343		"  for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4344		"    for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4345		"    g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4346		"    for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4347		"      g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4348		"      g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4349		"      g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4350		"      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 + "
4351		"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
4352		"    }" NL "  }" NL NL "  g_output_ssbo.a = g_input_ssbo.a;" NL "  g_output_ssbo.b = g_input_ssbo.b;" NL
4353		"  g_output_ssbo.c = g_input_ssbo.c;" NL
4354		"  for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4355		"  for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4356		"    g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4357		"    for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4358		"      g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4359		"      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
4360		"      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
4361		"      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 - "
4362		"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
4363		"  }" NL "}";
4364}
4365
4366class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4367{
4368	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4369	{
4370		return GetInputUBO2(in_data);
4371	}
4372};
4373
4374class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4375{
4376	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4377	{
4378		return GetInputUBO2(in_data);
4379	}
4380};
4381
4382//-----------------------------------------------------------------------------
4383// 1.12.x BasicMatrixOperationsBase
4384//-----------------------------------------------------------------------------
4385class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4386{
4387	GLuint m_program;
4388	GLuint m_buffer[2];
4389	GLuint m_vertex_array;
4390
4391	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4392
4393	static bool Equal(float a, float b)
4394	{
4395		return fabsf(a - b) < 0.001f;
4396	}
4397
4398	virtual long Setup()
4399	{
4400		m_program = 0;
4401		memset(m_buffer, 0, sizeof(m_buffer));
4402		m_vertex_array = 0;
4403		return NO_ERROR;
4404	}
4405
4406	virtual long Run()
4407	{
4408		if (!IsVSFSAvailable(2, 0))
4409			return NOT_SUPPORTED;
4410		std::vector<float> in;
4411		std::vector<float> expected;
4412		const char*		   glsl_vs = GetInput(in, expected);
4413		const char* const  glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
4414									   "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
4415
4416		m_program = CreateProgram(glsl_vs, glsl_fs);
4417		glLinkProgram(m_program);
4418		if (!CheckProgram(m_program))
4419			return ERROR;
4420
4421		glGenBuffers(2, m_buffer);
4422
4423		/* output buffer */
4424		{
4425			std::vector<float> zero(expected.size());
4426			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4427			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4428						 GL_STATIC_DRAW);
4429		}
4430		// input buffer
4431		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4432		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4433
4434		glGenVertexArrays(1, &m_vertex_array);
4435		glEnable(GL_RASTERIZER_DISCARD);
4436
4437		glUseProgram(m_program);
4438		glBindVertexArray(m_vertex_array);
4439		glDrawArrays(GL_POINTS, 0, 1);
4440
4441		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4442		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4443		float* out_data = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4444												   (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4445		if (!out_data)
4446			return ERROR;
4447
4448		bool status = true;
4449		for (size_t i = 0; i < expected.size(); ++i)
4450		{
4451			if (!Equal(expected[i], out_data[i]))
4452			{
4453				m_context.getTestContext().getLog()
4454					<< tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4455					<< " should be " << expected[i] << tcu::TestLog::EndMessage;
4456				status = false;
4457			}
4458		}
4459		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4460		if (!status)
4461			return ERROR;
4462		return NO_ERROR;
4463	}
4464
4465	virtual long Cleanup()
4466	{
4467		glDisable(GL_RASTERIZER_DISCARD);
4468		glUseProgram(0);
4469		glDeleteProgram(m_program);
4470		glDeleteBuffers(2, m_buffer);
4471		glDeleteVertexArrays(1, &m_vertex_array);
4472		return NO_ERROR;
4473	}
4474};
4475
4476class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4477{
4478	GLuint m_program;
4479	GLuint m_buffer[2];
4480
4481	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4482
4483	static bool Equal(float a, float b)
4484	{
4485		return fabsf(a - b) < 0.001f;
4486	}
4487
4488	virtual long Setup()
4489	{
4490		m_program = 0;
4491		memset(m_buffer, 0, sizeof(m_buffer));
4492		return NO_ERROR;
4493	}
4494
4495	virtual long Run()
4496	{
4497		std::vector<float> in;
4498		std::vector<float> expected;
4499		std::stringstream  ss;
4500		ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4501		m_program = CreateProgramCS(ss.str());
4502		glLinkProgram(m_program);
4503		if (!CheckProgram(m_program))
4504			return ERROR;
4505
4506		glGenBuffers(2, m_buffer);
4507
4508		/* output buffer */
4509		{
4510			std::vector<float> zero(expected.size());
4511			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4512			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4513						 GL_STATIC_DRAW);
4514		}
4515		// input buffer
4516		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4517		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4518
4519		glUseProgram(m_program);
4520		glDispatchCompute(1, 1, 1);
4521
4522		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4523		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4524		float* out_data = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4525												   (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4526		if (!out_data)
4527			return ERROR;
4528
4529		bool status = true;
4530		for (size_t i = 0; i < expected.size(); ++i)
4531		{
4532			if (!Equal(expected[i], out_data[i]))
4533			{
4534				m_context.getTestContext().getLog()
4535					<< tcu::TestLog::Message << "Float at index  " << static_cast<int>(i) << " is " << out_data[i]
4536					<< " should be " << expected[i] << tcu::TestLog::EndMessage;
4537				status = false;
4538			}
4539		}
4540		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4541		if (!status)
4542			return ERROR;
4543		return NO_ERROR;
4544	}
4545
4546	virtual long Cleanup()
4547	{
4548		glUseProgram(0);
4549		glDeleteProgram(m_program);
4550		glDeleteBuffers(2, m_buffer);
4551		return NO_ERROR;
4552	}
4553};
4554
4555//-----------------------------------------------------------------------------
4556// 1.12.1 BasicMatrixOperationsCase1
4557//-----------------------------------------------------------------------------
4558const char* GetInputM1(std::vector<float>& in, std::vector<float>& expected)
4559{
4560	in.resize(8);
4561	in[0] = 1.0f;
4562	in[2] = 3.0f;
4563	in[1] = 2.0f;
4564	in[3] = 4.0f;
4565	in[4] = 1.0f;
4566	in[6] = 3.0f;
4567	in[5] = 2.0f;
4568	in[7] = 4.0f;
4569	expected.resize(4);
4570	expected[0] = 7.0f;
4571	expected[2] = 15.0f;
4572	expected[1] = 10.0f;
4573	expected[3] = 22.0f;
4574	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat2 m0;" NL "  mat2 m1;" NL "} g_input;" NL
4575			  "layout(std430, binding = 1) buffer Output {" NL "  mat2 m;" NL "} g_output;" NL
4576			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4577}
4578
4579class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4580{
4581	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4582	{
4583		return GetInputM1(in, expected);
4584	}
4585};
4586
4587class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4588{
4589	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4590	{
4591		return GetInputM1(in, expected);
4592	}
4593};
4594
4595//-----------------------------------------------------------------------------
4596// 1.12.2 BasicMatrixOperationsCase2
4597//-----------------------------------------------------------------------------
4598const char* GetInputM2(std::vector<float>& in, std::vector<float>& expected)
4599{
4600	in.resize(15);
4601	expected.resize(4);
4602	// mat3x2
4603	in[0] = 1.0f;
4604	in[2] = 3.0f;
4605	in[4] = 5.0f;
4606	in[1] = 2.0f;
4607	in[3] = 4.0f;
4608	in[5] = 6.0f;
4609	// mat2x3
4610	in[8]  = 1.0f;
4611	in[12] = 4.0f;
4612	in[9]  = 2.0f;
4613	in[13] = 5.0f;
4614	in[10] = 3.0f;
4615	in[14] = 6.0f;
4616	// mat2
4617	expected[0] = 22.0f;
4618	expected[2] = 49.0f;
4619	expected[1] = 28.0f;
4620	expected[3] = 64.0f;
4621	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4622			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4623			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
4624			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4625}
4626
4627class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4628{
4629	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4630	{
4631		return GetInputM2(in, expected);
4632	}
4633};
4634
4635class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4636{
4637	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4638	{
4639		return GetInputM2(in, expected);
4640	}
4641};
4642
4643//-----------------------------------------------------------------------------
4644// 1.12.3 BasicMatrixOperationsCase3
4645//-----------------------------------------------------------------------------
4646const char* GetInputM3(std::vector<float>& in, std::vector<float>& expected)
4647{
4648	in.resize(15);
4649	expected.resize(4);
4650	// row major mat3x2
4651	in[0] = 1.0f;
4652	in[1] = 3.0f;
4653	in[2] = 5.0f;
4654	in[4] = 2.0f;
4655	in[5] = 4.0f;
4656	in[6] = 6.0f;
4657	// row major mat2x3
4658	in[8]  = 1.0f;
4659	in[9]  = 4.0f;
4660	in[10] = 2.0f;
4661	in[11] = 5.0f;
4662	in[12] = 3.0f;
4663	in[13] = 6.0f;
4664	// row major mat2
4665	expected[0] = 22.0f;
4666	expected[1] = 49.0f;
4667	expected[2] = 28.0f;
4668	expected[3] = 64.0f;
4669
4670	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4671			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4672			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4673}
4674
4675class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4676{
4677	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4678	{
4679		return GetInputM3(in, expected);
4680	}
4681};
4682
4683class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4684{
4685	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4686	{
4687		return GetInputM3(in, expected);
4688	}
4689};
4690
4691//-----------------------------------------------------------------------------
4692// 1.12.4 BasicMatrixOperationsCase4
4693//-----------------------------------------------------------------------------
4694const char* GetInputM4(std::vector<float>& in, std::vector<float>& expected)
4695{
4696	in.resize(15);
4697	expected.resize(4);
4698	// column major mat3x2
4699	in[0] = 1.0f;
4700	in[2] = 3.0f;
4701	in[4] = 5.0f;
4702	in[1] = 2.0f;
4703	in[3] = 4.0f;
4704	in[5] = 6.0f;
4705	// row major mat2x3
4706	in[8]  = 1.0f;
4707	in[9]  = 4.0f;
4708	in[10] = 2.0f;
4709	in[11] = 5.0f;
4710	in[12] = 3.0f;
4711	in[13] = 6.0f;
4712	// column major mat2
4713	expected[0] = 13.0f;
4714	expected[1] = 16.0f;
4715	expected[2] = 37.0f;
4716	expected[3] = 46.0f;
4717	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4718			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4719			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
4720			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4721}
4722
4723class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4724{
4725	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4726	{
4727		return GetInputM4(in, expected);
4728	}
4729};
4730
4731class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4732{
4733	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4734	{
4735		return GetInputM4(in, expected);
4736	}
4737};
4738
4739//-----------------------------------------------------------------------------
4740// 1.12.5 BasicMatrixOperationsCase5
4741//-----------------------------------------------------------------------------
4742const char* GetInputM5(std::vector<float>& in, std::vector<float>& expected)
4743{
4744	in.resize(15);
4745	expected.resize(4);
4746	// column major mat3x2
4747	in[0] = 1.0f;
4748	in[2] = 3.0f;
4749	in[4] = 5.0f;
4750	in[1] = 2.0f;
4751	in[3] = 4.0f;
4752	in[5] = 6.0f;
4753	// row major mat2x3
4754	in[8]  = 1.0f;
4755	in[9]  = 4.0f;
4756	in[10] = 2.0f;
4757	in[11] = 5.0f;
4758	in[12] = 3.0f;
4759	in[13] = 6.0f;
4760	// row major mat2
4761	expected[0] = 13.0f;
4762	expected[1] = 37.0f;
4763	expected[2] = 16.0f;
4764	expected[3] = 46.0f;
4765	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4766			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4767			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4768}
4769
4770class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4771{
4772	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4773	{
4774		return GetInputM5(in, expected);
4775	}
4776};
4777
4778class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4779{
4780	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4781	{
4782		return GetInputM5(in, expected);
4783	}
4784};
4785
4786//-----------------------------------------------------------------------------
4787// 1.12.6 BasicMatrixOperationsCase6
4788//-----------------------------------------------------------------------------
4789const char* GetInputM6(std::vector<float>& in, std::vector<float>& expected)
4790{
4791	in.resize(20);
4792	expected.resize(4);
4793	// row major mat3x2
4794	in[0] = 1.0f;
4795	in[1] = 3.0f;
4796	in[2] = 5.0f;
4797	in[4] = 2.0f;
4798	in[5] = 4.0f;
4799	in[6] = 6.0f;
4800	// column major mat2x3
4801	in[8]  = 1.0f;
4802	in[12] = 4.0f;
4803	in[9]  = 2.0f;
4804	in[13] = 5.0f;
4805	in[10] = 3.0f;
4806	in[14] = 6.0f;
4807	// column major mat2
4808	expected[0] = 22.0f;
4809	expected[1] = 28.0f;
4810	expected[2] = 49.0f;
4811	expected[3] = 64.0f;
4812	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4813			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4814			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
4815			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4816}
4817
4818class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
4819{
4820	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4821	{
4822		return GetInputM6(in, expected);
4823	}
4824};
4825
4826class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
4827{
4828	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4829	{
4830		return GetInputM6(in, expected);
4831	}
4832};
4833
4834//-----------------------------------------------------------------------------
4835// 1.12.7 BasicMatrixOperationsCase7
4836//-----------------------------------------------------------------------------
4837const char* GetInputM7(std::vector<float>& in, std::vector<float>& expected)
4838{
4839	in.resize(20);
4840	expected.resize(4);
4841	// row major mat3x2
4842	in[0] = 1.0f;
4843	in[1] = 3.0f;
4844	in[2] = 5.0f;
4845	in[4] = 2.0f;
4846	in[5] = 4.0f;
4847	in[6] = 6.0f;
4848	// column major mat2x3
4849	in[8]  = 1.0f;
4850	in[12] = 4.0f;
4851	in[9]  = 2.0f;
4852	in[13] = 5.0f;
4853	in[10] = 3.0f;
4854	in[14] = 6.0f;
4855	// row major mat2
4856	expected[0] = 22.0f;
4857	expected[1] = 49.0f;
4858	expected[2] = 28.0f;
4859	expected[3] = 64.0f;
4860	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4861			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4862			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4863}
4864
4865class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
4866{
4867	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4868	{
4869		return GetInputM7(in, expected);
4870	}
4871};
4872
4873class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
4874{
4875	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4876	{
4877		return GetInputM7(in, expected);
4878	}
4879};
4880
4881//-----------------------------------------------------------------------------
4882// 2.1 AdvancedSwitchBuffers
4883//-----------------------------------------------------------------------------
4884class AdvancedSwitchBuffersVS : public ShaderStorageBufferObjectBase
4885{
4886	virtual std::string PassCriteria()
4887	{
4888		return NL "Everything works as expected.";
4889	}
4890
4891	GLuint m_program;
4892	GLuint m_storage_buffer[5];
4893	GLuint m_vertex_array;
4894	GLuint m_fbo, m_rt;
4895
4896	virtual long Setup()
4897	{
4898		m_program = 0;
4899		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
4900		m_vertex_array = 0;
4901		glGenFramebuffers(1, &m_fbo);
4902		glGenTextures(1, &m_rt);
4903		return NO_ERROR;
4904	}
4905
4906	virtual long Run()
4907	{
4908		if (!IsVSFSAvailable(1, 0))
4909			return NOT_SUPPORTED;
4910		const char* const glsl_vs = NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
4911									   "layout(binding = 0, std430) buffer Input {" NL "  VertexData vertex[4];" NL
4912									   "} g_vs_in;" NL "out vec3 StageData_color;" NL "void main() {" NL
4913									   "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
4914									   "  StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
4915		const char* const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
4916									   "void main() {" NL "  g_fs_out = vec4(StageData_color, 1);" NL "}";
4917		m_program = CreateProgram(glsl_vs, glsl_fs);
4918		glLinkProgram(m_program);
4919		if (!CheckProgram(m_program))
4920			return ERROR;
4921
4922		glGenBuffers(5, m_storage_buffer);
4923
4924		/* left, bottom, red quad */
4925		{
4926			const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
4927								   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			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
4931			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4932		}
4933		/* right, bottom, green quad */
4934		{
4935			const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
4936								   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			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
4940			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4941		}
4942		/* left, top, blue quad */
4943		{
4944			const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
4945								   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			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
4949			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4950		}
4951		/* right, top, yellow quad */
4952		{
4953			const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
4954								   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			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
4958			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4959		}
4960
4961		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
4962		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
4963
4964		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
4965		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
4966		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
4967		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
4968		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
4969		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
4970							sizeof(float) * 32);
4971		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
4972		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
4973							sizeof(float) * 32);
4974
4975		glBindTexture(GL_TEXTURE_2D, m_rt);
4976		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4977		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4978		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
4979		glBindTexture(GL_TEXTURE_2D, 0);
4980		glViewport(0, 0, 100, 100);
4981		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
4982		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
4983
4984		glGenVertexArrays(1, &m_vertex_array);
4985
4986		glUseProgram(m_program);
4987		glBindVertexArray(m_vertex_array);
4988
4989		glClear(GL_COLOR_BUFFER_BIT);
4990		for (int i = 0; i < 4; ++i)
4991		{
4992			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
4993			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4994		}
4995		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
4996		{
4997			return ERROR;
4998		}
4999
5000		glClear(GL_COLOR_BUFFER_BIT);
5001		for (int i = 0; i < 4; ++i)
5002		{
5003			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5004							  sizeof(float) * 32);
5005			glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5006		}
5007		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5008		{
5009			return ERROR;
5010		}
5011
5012		return NO_ERROR;
5013	}
5014
5015	virtual long Cleanup()
5016	{
5017		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5018		glUseProgram(0);
5019		glDeleteProgram(m_program);
5020		glDeleteBuffers(5, m_storage_buffer);
5021		glDeleteVertexArrays(1, &m_vertex_array);
5022		glDeleteFramebuffers(1, &m_fbo);
5023		glDeleteTextures(1, &m_rt);
5024		return NO_ERROR;
5025	}
5026};
5027class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5028{
5029	GLuint m_program;
5030	GLuint m_storage_buffer[6];
5031
5032	virtual long Setup()
5033	{
5034		m_program = 0;
5035		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5036		return NO_ERROR;
5037	}
5038
5039	virtual long Run()
5040	{
5041		const char* const glsl_cs =
5042			NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL "  uint cookie[4];" NL
5043			   "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL
5044			   "void main() {" NL "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5045			   "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5046			   "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5047			   "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5048			   "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5049		m_program = CreateProgramCS(glsl_cs);
5050		glLinkProgram(m_program);
5051		if (!CheckProgram(m_program))
5052			return ERROR;
5053
5054		glGenBuffers(6, m_storage_buffer);
5055
5056		const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5057		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5058		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5059		const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5060		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5061		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5062		const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5063		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5064		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5065		const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5066		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5067		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5068
5069		GLint alignment;
5070		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5071		GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5072		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5073		glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5074
5075		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5076		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5077		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5078		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5079		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5080		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5081		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5082		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5083
5084		const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5085		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5086		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5087
5088		glUseProgram(m_program);
5089		for (int i = 0; i < 4; ++i)
5090		{
5091			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5092			glDispatchCompute(1, 1, 1);
5093		}
5094		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5095		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5096		GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5097		if (!out_data)
5098			return ERROR;
5099		GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5100		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5101			out_data[3] != expected[3])
5102		{
5103			m_context.getTestContext().getLog()
5104				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5105				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5106				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5107				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5108			return ERROR;
5109		}
5110		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5111		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5112
5113		for (int i = 0; i < 4; ++i)
5114		{
5115			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5116			glDispatchCompute(1, 1, 1);
5117		}
5118		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5119		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5120		out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5121		if (!out_data)
5122			return ERROR;
5123		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5124			out_data[3] != expected[3])
5125		{
5126			m_context.getTestContext().getLog()
5127				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5128				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5129				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5130				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5131			return ERROR;
5132		}
5133
5134		return NO_ERROR;
5135	}
5136
5137	virtual long Cleanup()
5138	{
5139		glUseProgram(0);
5140		glDeleteProgram(m_program);
5141		glDeleteBuffers(6, m_storage_buffer);
5142		return NO_ERROR;
5143	}
5144};
5145//-----------------------------------------------------------------------------
5146// 2.2 AdvancedSwitchPrograms
5147//-----------------------------------------------------------------------------
5148class AdvancedSwitchProgramsVS : public ShaderStorageBufferObjectBase
5149{
5150	GLuint m_program[4];
5151	GLuint m_storage_buffer[4];
5152	GLuint m_vertex_array;
5153	GLuint m_fbo, m_rt;
5154
5155	std::string GenSource(int binding)
5156	{
5157		std::stringstream ss;
5158		ss << NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL "layout(binding = "
5159		   << binding
5160		   << ", std430) buffer Input {" NL "  VertexData vertex[4];" NL "} g_vs_in;" NL "out vec3 StageData_color;" NL
5161			  "void main() {" NL "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5162			  "  StageData_color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5163		return ss.str();
5164	}
5165
5166	virtual long Setup()
5167	{
5168		memset(m_program, 0, sizeof(m_program));
5169		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5170		m_vertex_array = 0;
5171		glGenFramebuffers(1, &m_fbo);
5172		glGenTextures(1, &m_rt);
5173		return NO_ERROR;
5174	}
5175
5176	virtual long Run()
5177	{
5178		if (!IsVSFSAvailable(1, 0))
5179			return NOT_SUPPORTED;
5180		const char* const glsl_fs = NL "in vec3 StageData_color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5181									   "void main() {" NL "  g_fs_out = vec4(StageData_color, 1);" NL "}";
5182		for (int i = 0; i < 4; ++i)
5183		{
5184			m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5185			glLinkProgram(m_program[i]);
5186			if (!CheckProgram(m_program[i]))
5187				return ERROR;
5188		}
5189
5190		glGenBuffers(4, m_storage_buffer);
5191
5192		/* left, bottom, red quad */
5193		{
5194			const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5195								   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			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5199			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5200		}
5201		/* right, bottom, green quad */
5202		{
5203			const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5204								   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			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5208			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5209		}
5210		/* left, top, blue quad */
5211		{
5212			const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5213								   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			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5217			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5218		}
5219		/* right, top, yellow quad */
5220		{
5221			const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5222								   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			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5226			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5227		}
5228
5229		glBindTexture(GL_TEXTURE_2D, m_rt);
5230		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5231		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5232		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5233		glBindTexture(GL_TEXTURE_2D, 0);
5234		glViewport(0, 0, 100, 100);
5235		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5236		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5237
5238		glGenVertexArrays(1, &m_vertex_array);
5239		glBindVertexArray(m_vertex_array);
5240
5241		glClear(GL_COLOR_BUFFER_BIT);
5242		for (int i = 0; i < 4; ++i)
5243		{
5244			glUseProgram(m_program[i]);
5245			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5246		}
5247		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5248		{
5249			return ERROR;
5250		}
5251
5252		return NO_ERROR;
5253	}
5254
5255	virtual long Cleanup()
5256	{
5257		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5258		glUseProgram(0);
5259		for (int i = 0; i < 4; ++i)
5260			glDeleteProgram(m_program[i]);
5261		glDeleteBuffers(4, m_storage_buffer);
5262		glDeleteVertexArrays(1, &m_vertex_array);
5263		glDeleteFramebuffers(1, &m_fbo);
5264		glDeleteTextures(1, &m_rt);
5265		return NO_ERROR;
5266	}
5267};
5268class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5269{
5270	GLuint m_program[4];
5271	GLuint m_storage_buffer[5];
5272
5273	virtual long Setup()
5274	{
5275		memset(m_program, 0, sizeof(m_program));
5276		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5277		return NO_ERROR;
5278	}
5279
5280	std::string GenSource(int binding)
5281	{
5282		std::stringstream ss;
5283		ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5284		   << ", std430) buffer Input {" NL "  uint cookie[4];" NL "} g_in;" NL
5285			  "layout(binding = 0, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL "void main() {" NL
5286			  "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5287			  "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5288			  "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5289			  "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5290			  "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5291		return ss.str();
5292	}
5293
5294	virtual long Run()
5295	{
5296		for (int i = 0; i < 4; ++i)
5297		{
5298			m_program[i] = CreateProgramCS(GenSource(i + 1));
5299			glLinkProgram(m_program[i]);
5300			if (!CheckProgram(m_program[i]))
5301				return ERROR;
5302		}
5303
5304		glGenBuffers(5, m_storage_buffer);
5305
5306		const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5307		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5308		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5309		const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5310		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5311		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5312		const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5313		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5314		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5315		const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5316		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5317		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5318
5319		const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5320		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5321		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5322
5323		for (int i = 0; i < 4; ++i)
5324		{
5325			glUseProgram(m_program[i]);
5326			glDispatchCompute(1, 1, 1);
5327		}
5328		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5329		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5330		GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5331		if (!out_data)
5332			return ERROR;
5333		GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5334		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5335			out_data[3] != expected[3])
5336		{
5337			m_context.getTestContext().getLog()
5338				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5339				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5340				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5341				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << ", " << tcu::TestLog::EndMessage;
5342			return ERROR;
5343		}
5344		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5345
5346		return NO_ERROR;
5347	}
5348
5349	virtual long Cleanup()
5350	{
5351		glUseProgram(0);
5352		for (int i = 0; i < 4; ++i)
5353			glDeleteProgram(m_program[i]);
5354		glDeleteBuffers(5, m_storage_buffer);
5355		return NO_ERROR;
5356	}
5357};
5358
5359//-----------------------------------------------------------------------------
5360// 2.3.1 AdvancedWriteFragment
5361//-----------------------------------------------------------------------------
5362class AdvancedWriteFragmentFS : public ShaderStorageBufferObjectBase
5363{
5364	GLuint m_program[2];
5365	GLuint m_storage_buffer;
5366	GLuint m_counter_buffer;
5367	GLuint m_attribless_vertex_array;
5368	GLuint m_draw_vertex_array;
5369	GLuint m_fbo, m_rt;
5370
5371	virtual long Setup()
5372	{
5373		memset(m_program, 0, sizeof(m_program));
5374		m_storage_buffer		  = 0;
5375		m_counter_buffer		  = 0;
5376		m_attribless_vertex_array = 0;
5377		m_draw_vertex_array		  = 0;
5378		glGenFramebuffers(1, &m_fbo);
5379		glGenTextures(1, &m_rt);
5380		return NO_ERROR;
5381	}
5382
5383	virtual long Run()
5384	{
5385		if (!IsVSFSAvailable(0, 1))
5386			return NOT_SUPPORTED;
5387		const char* const glsl_vs0 =
5388			NL "out vec2 position;" NL "out vec3 color;" NL
5389			   "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
5390			   "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
5391			   "vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5392			   "void main() {" NL "  vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5393			   "  gl_Position = vec4(pos, 0, 1);" NL "  position = pos;" NL "  color = g_color[gl_InstanceID];" NL "}";
5394		const char* const glsl_fs0 =
5395			NL "in vec2 position;" NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5396			   "struct FragmentData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5397			   "layout(std430, binding = 3) buffer Output {" NL "  FragmentData g_fragment[6400];" NL "};" NL
5398			   "uniform uint g_max_fragment_count;" NL
5399			   "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5400			   "  uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5401			   "  if (fragment_number < g_max_fragment_count) {" NL
5402			   "    g_fragment[fragment_number].position = position;" NL
5403			   "    g_fragment[fragment_number].color = color;" NL "  }" NL "  g_fs_out = vec4(color, 1);" NL "}";
5404		m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5405		glLinkProgram(m_program[0]);
5406		if (!CheckProgram(m_program[0]))
5407			return ERROR;
5408
5409		const char* const glsl_vs1 =
5410			NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5411			   "out vec3 color;" NL "void main() {" NL "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5412			   "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "  color = g_in_color.rgb;" NL "}";
5413		const char* const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5414										"void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5415		m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5416		glLinkProgram(m_program[1]);
5417		if (!CheckProgram(m_program[1]))
5418			return ERROR;
5419
5420		// The first pass renders four squares on-screen, and writes a
5421		// record to the SSBO for each fragment processed.  The rectangles
5422		// will be 40x40 when using a 100x100 viewport, so we expect 1600
5423		// pixels per rectangle or 6400 pixels total.  Size the SSBO
5424		// accordingly, and render the second pass (sourcing the SSBO as a
5425		// vertex buffer) with an identical number of points.  If we have
5426		// a larger buffer and draw more points on the second pass, those
5427		// may overwrite "real" points using garbage position/color.
5428		int expectedPixels = 6400;
5429
5430		glGenBuffers(1, &m_storage_buffer);
5431		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5432		glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5433
5434		glGenBuffers(1, &m_counter_buffer);
5435		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5436		glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5437		uvec4 zero(0);
5438		glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5439
5440		glBindTexture(GL_TEXTURE_2D, m_rt);
5441		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5442		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5443		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5444		glBindTexture(GL_TEXTURE_2D, 0);
5445		glViewport(0, 0, 100, 100);
5446		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5447		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5448
5449		glGenVertexArrays(1, &m_attribless_vertex_array);
5450
5451		glGenVertexArrays(1, &m_draw_vertex_array);
5452		glBindVertexArray(m_draw_vertex_array);
5453		glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5454		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5455		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void*>(16));
5456		glBindBuffer(GL_ARRAY_BUFFER, 0);
5457		glEnableVertexAttribArray(0);
5458		glEnableVertexAttribArray(1);
5459		glBindVertexArray(0);
5460
5461		glClear(GL_COLOR_BUFFER_BIT);
5462		glUseProgram(m_program[0]);
5463		glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5464		glBindVertexArray(m_attribless_vertex_array);
5465		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5466		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5467		{
5468			return ERROR;
5469		}
5470
5471		glClear(GL_COLOR_BUFFER_BIT);
5472		glUseProgram(m_program[1]);
5473		glBindVertexArray(m_draw_vertex_array);
5474		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5475		glDrawArrays(GL_POINTS, 0, expectedPixels);
5476		int bad_pixels;
5477		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5478			bad_pixels > 2)
5479		{
5480			return ERROR;
5481		}
5482
5483		return NO_ERROR;
5484	}
5485
5486	virtual long Cleanup()
5487	{
5488		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5489		glUseProgram(0);
5490		for (int i = 0; i < 2; ++i)
5491			glDeleteProgram(m_program[i]);
5492		glDeleteBuffers(1, &m_storage_buffer);
5493		glDeleteBuffers(1, &m_counter_buffer);
5494		glDeleteVertexArrays(1, &m_attribless_vertex_array);
5495		glDeleteVertexArrays(1, &m_draw_vertex_array);
5496		glDeleteFramebuffers(1, &m_fbo);
5497		glDeleteTextures(1, &m_rt);
5498		return NO_ERROR;
5499	}
5500};
5501
5502class AdvancedWriteFragmentCS : public ShaderStorageBufferObjectBase
5503{
5504	GLuint m_program[2];
5505	GLuint m_storage_buffer;
5506	GLuint m_counter_buffer;
5507	GLuint m_draw_vertex_array;
5508	GLuint m_fbo, m_rt;
5509
5510	virtual long Setup()
5511	{
5512		memset(m_program, 0, sizeof(m_program));
5513		m_storage_buffer	= 0;
5514		m_counter_buffer	= 0;
5515		m_draw_vertex_array = 0;
5516		glGenFramebuffers(1, &m_fbo);
5517		glGenTextures(1, &m_rt);
5518		return NO_ERROR;
5519	}
5520
5521	virtual long Run()
5522	{
5523		const char* const glsl_cs = NL
5524			"layout(local_size_x = 10, local_size_y = 10) in;" NL "uniform uint g_max_point_count;" NL
5525			"uniform uint g_brick;" NL
5526			"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
5527			"struct PointData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5528			"layout(std430, binding = 3) buffer Output {" NL "  PointData g_point[];" NL "};" NL
5529			"layout(binding = 0, offset = 0) uniform atomic_uint g_point_counter;" NL "void main() {" NL
5530			"  uint g_offset[4] = uint[4](g_brick, 9u*g_brick, 11u*g_brick, 19u*g_brick);" NL
5531			"  uint point_number = atomicCounterIncrement(g_point_counter);" NL
5532			"  uint giidx = gl_GlobalInvocationID.x;" NL "  uint giidy = gl_GlobalInvocationID.y;" NL
5533			"  g_point[point_number].position = vec2(gl_GlobalInvocationID.xy * 2u) / 100.0 - 1.0;" NL
5534			"  g_point[point_number].color = g_color[4];" NL "  if (point_number < g_max_point_count) {" NL
5535			"    if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5536			"      g_point[point_number].color = g_color[0];" NL "    }" NL
5537			"    if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[0] && giidy < g_offset[1]) {" NL
5538			"      g_point[point_number].color = g_color[1];" NL "    }" NL
5539			"    if (giidx > g_offset[2] && giidx < g_offset[3] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5540			"      g_point[point_number].color = g_color[2];" NL "    }" NL
5541			"    if (giidx > g_offset[0] && giidx < g_offset[1] && giidy > g_offset[2] && giidy < g_offset[3]) {" NL
5542			"      g_point[point_number].color = g_color[3];" NL "    }" NL "  }" NL "}";
5543		m_program[0] = CreateProgramCS(glsl_cs);
5544		glLinkProgram(m_program[0]);
5545		if (!CheckProgram(m_program[0]))
5546			return ERROR;
5547
5548		const char* const glsl_vs1 =
5549			NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5550			   "out vec3 color;" NL "void main() {" NL "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL
5551			   "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "  color = g_in_color.rgb;" NL "}";
5552		const char* const glsl_fs1 = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5553										"void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5554		m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5555		glLinkProgram(m_program[1]);
5556		if (!CheckProgram(m_program[1]))
5557			return ERROR;
5558
5559		glGenBuffers(1, &m_storage_buffer);
5560		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5561		glBufferData(GL_SHADER_STORAGE_BUFFER, 100 * 100 * 32, NULL, GL_DYNAMIC_DRAW);
5562
5563		glGenBuffers(1, &m_counter_buffer);
5564		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
5565		glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5566		uvec4 zero(0);
5567		glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5568
5569		glGenVertexArrays(1, &m_draw_vertex_array);
5570		glBindVertexArray(m_draw_vertex_array);
5571		glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5572		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5573		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void*>(16));
5574		glBindBuffer(GL_ARRAY_BUFFER, 0);
5575		glEnableVertexAttribArray(0);
5576		glEnableVertexAttribArray(1);
5577		glBindVertexArray(0);
5578
5579		glUseProgram(m_program[0]);
5580		glUniform1ui(glGetUniformLocation(m_program[0], "g_max_point_count"), 100 * 100);
5581		glUniform1ui(glGetUniformLocation(m_program[0], "g_brick"), 5);
5582		glDispatchCompute(10, 10, 1);
5583
5584		glBindTexture(GL_TEXTURE_2D, m_rt);
5585		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5586		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5587		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5588		glBindTexture(GL_TEXTURE_2D, 0);
5589		glViewport(0, 0, 100, 100);
5590		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5591		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5592
5593		glClear(GL_COLOR_BUFFER_BIT);
5594		glUseProgram(m_program[1]);
5595		glBindVertexArray(m_draw_vertex_array);
5596		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5597		glDrawArrays(GL_POINTS, 0, 100 * 100);
5598		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5599		{
5600			return ERROR;
5601		}
5602
5603		return NO_ERROR;
5604	}
5605
5606	virtual long Cleanup()
5607	{
5608		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5609		glUseProgram(0);
5610		for (int i = 0; i < 2; ++i)
5611			glDeleteProgram(m_program[i]);
5612		glDeleteBuffers(1, &m_storage_buffer);
5613		glDeleteBuffers(1, &m_counter_buffer);
5614		glDeleteVertexArrays(1, &m_draw_vertex_array);
5615		glDeleteFramebuffers(1, &m_fbo);
5616		glDeleteTextures(1, &m_rt);
5617		return NO_ERROR;
5618	}
5619};
5620
5621//-----------------------------------------------------------------------------
5622// 2.4.1 AdvancedIndirectAddressingCase1
5623//-----------------------------------------------------------------------------
5624class AdvancedIndirectAddressingCase1VS : public ShaderStorageBufferObjectBase
5625{
5626	GLuint m_program;
5627	GLuint m_storage_buffer[4];
5628	GLuint m_vertex_array;
5629	GLuint m_vertex_buffer;
5630	GLuint m_fbo, m_rt;
5631
5632	virtual long Setup()
5633	{
5634		m_program = 0;
5635		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5636		m_vertex_array  = 0;
5637		m_vertex_buffer = 0;
5638		glGenFramebuffers(1, &m_fbo);
5639		glGenTextures(1, &m_rt);
5640		return NO_ERROR;
5641	}
5642
5643	virtual long Run()
5644	{
5645		if (!IsVSFSAvailable(4, 0))
5646			return NOT_SUPPORTED;
5647		const char* const glsl_vs =
5648			NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
5649			   "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
5650			   "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
5651			   "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
5652			   "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
5653			   "out vec3 color;" NL "void main() {" NL "  uint mid = g_material_id[gl_InstanceID];" NL
5654			   "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_InstanceID];" NL
5655			   "  vec2 t = g_transform.translation[tid];" NL "  gl_Position = vec4(g_in_position + t, 0, 1);" NL
5656			   "  color = m.color;" NL "}";
5657		const char* const glsl_fs = NL "in vec3 color;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5658									   "void main() {" NL "  g_fs_out = vec4(color, 1);" NL "}";
5659		m_program = CreateProgram(glsl_vs, glsl_fs);
5660		glLinkProgram(m_program);
5661		if (!CheckProgram(m_program))
5662			return ERROR;
5663
5664		glGenBuffers(4, m_storage_buffer);
5665
5666		/* material buffer */
5667		{
5668			const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5669								   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
5670			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5671			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5672		}
5673		/* material id buffer */
5674		{
5675			const unsigned int data[] = { 2, 3, 0, 2 };
5676			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5677			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5678		}
5679		/* transform buffer */
5680		{
5681			const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
5682			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5683			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5684		}
5685		/* transform id buffer */
5686		{
5687			const unsigned int data[] = { 3, 1, 0, 2 };
5688			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5689			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5690		}
5691
5692		/* vertex buffer */
5693		{
5694			const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
5695			glGenBuffers(1, &m_vertex_buffer);
5696			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5697			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5698			glBindBuffer(GL_ARRAY_BUFFER, 0);
5699		}
5700
5701		glBindTexture(GL_TEXTURE_2D, m_rt);
5702		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5703		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5704		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5705		glBindTexture(GL_TEXTURE_2D, 0);
5706		glViewport(0, 0, 100, 100);
5707		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5708		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
5709
5710		glGenVertexArrays(1, &m_vertex_array);
5711		glBindVertexArray(m_vertex_array);
5712		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5713		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5714		glBindBuffer(GL_ARRAY_BUFFER, 0);
5715		glEnableVertexAttribArray(0);
5716		glBindVertexArray(0);
5717
5718		glClear(GL_COLOR_BUFFER_BIT);
5719		glUseProgram(m_program);
5720		glBindVertexArray(m_vertex_array);
5721		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5722		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
5723		{
5724			return ERROR;
5725		}
5726
5727		/* update material id buffer with BufferSubData */
5728		{
5729			const unsigned int data[] = { 3, 2, 1, 0 };
5730			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5731			glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5732		}
5733
5734		/* update transform id buffer with BufferData */
5735		{
5736			const unsigned int data[] = { 0, 1, 2, 3 };
5737			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5738			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5739		}
5740
5741		glClear(GL_COLOR_BUFFER_BIT);
5742		glUseProgram(m_program);
5743		glBindVertexArray(m_vertex_array);
5744		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5745		if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
5746		{
5747			return ERROR;
5748		}
5749
5750		return NO_ERROR;
5751	}
5752
5753	virtual long Cleanup()
5754	{
5755		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5756		glUseProgram(0);
5757		glDeleteProgram(m_program);
5758		glDeleteBuffers(4, m_storage_buffer);
5759		glDeleteBuffers(1, &m_vertex_buffer);
5760		glDeleteVertexArrays(1, &m_vertex_array);
5761		glDeleteFramebuffers(1, &m_fbo);
5762		glDeleteTextures(1, &m_rt);
5763		return NO_ERROR;
5764	}
5765};
5766
5767class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
5768{
5769	GLuint m_program;
5770	GLuint m_storage_buffer[5];
5771
5772	virtual long Setup()
5773	{
5774		m_program = 0;
5775		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5776		return NO_ERROR;
5777	}
5778
5779	virtual long Run()
5780	{
5781		bool			  status = true;
5782		const char* const glsl_cs =
5783			NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
5784			   "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
5785			   "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
5786			   "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
5787			   "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
5788			   "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[16];" NL "  vec2 pos[16];" NL
5789			   "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
5790			   "vec2(0.4f, 0.4f));" NL "void main() {" NL "  uint mid = g_material_id[gl_WorkGroupID.x];" NL
5791			   "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_WorkGroupID.x];" NL
5792			   "  vec2 t = g_transform.translation[tid];" NL
5793			   "  pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
5794			   "    = g_in_position[gl_LocalInvocationIndex] + t;" NL "  color[gl_LocalInvocationIndex + "
5795			   "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
5796			   "gl_WorkGroupSize.y] = m.color;" NL "}";
5797		m_program = CreateProgramCS(glsl_cs);
5798		glLinkProgram(m_program);
5799		if (!CheckProgram(m_program))
5800			return ERROR;
5801
5802		glGenBuffers(5, m_storage_buffer);
5803
5804		/* material buffer */
5805		{
5806			const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
5807								   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
5808			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5809			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5810		}
5811		/* material id buffer */
5812		{
5813			const unsigned int data[] = { 2, 3, 0, 2 };
5814			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5815			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5816		}
5817		/* transform buffer */
5818		{
5819			const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
5820			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5821			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5822		}
5823		/* transform id buffer */
5824		{
5825			const unsigned int data[] = { 3, 1, 0, 2 };
5826			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5827			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5828		}
5829
5830		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5831		glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
5832
5833		glUseProgram(m_program);
5834		glDispatchCompute(4, 1, 1);
5835		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5836		GLfloat* out_data =
5837			(GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5838		if (!out_data)
5839			return ERROR;
5840
5841		GLfloat expected[16 * 4 + 16 * 2] = {
5842			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,
5843			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,
5844			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,
5845			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,
5846			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,
5847			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,
5848			-0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f,  -0.1f, 0.1f,  -0.9f, 0.9f,  -0.1f, 0.9f
5849		};
5850		for (int i = 0; i < 16; ++i)
5851		{
5852			if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
5853				out_data[i * 4 + 2] != expected[i * 4 + 2])
5854			{
5855				m_context.getTestContext().getLog()
5856					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
5857					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
5858					<< expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5859				status = false;
5860			}
5861		}
5862		for (int i = 32; i < 32 + 16; ++i)
5863		{
5864			if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
5865				fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
5866			{
5867				m_context.getTestContext().getLog()
5868					<< tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
5869					<< ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1] << ", "
5870					<< tcu::TestLog::EndMessage;
5871				status = false;
5872			}
5873		}
5874		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5875
5876		/* update material id buffer with BufferSubData */
5877		{
5878			const unsigned int data[] = { 3, 2, 1, 0 };
5879			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5880			glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
5881		}
5882
5883		/* update transform id buffer with BufferData */
5884		{
5885			const unsigned int data[] = { 0, 1, 2, 3 };
5886			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5887			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
5888		}
5889
5890		glUseProgram(m_program);
5891		glDispatchCompute(4, 1, 1);
5892		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5893		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5894		GLfloat* out_data2 =
5895			(GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
5896		if (!out_data2)
5897			return ERROR;
5898
5899		GLfloat expected2[16 * 4 + 16 * 2] = {
5900			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,
5901			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,
5902			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,
5903			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,
5904			-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,
5905			-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
5906		};
5907		for (int i = 0; i < 16; ++i)
5908		{
5909			if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
5910				out_data2[i * 4 + 2] != expected2[i * 4 + 2])
5911			{
5912				m_context.getTestContext().getLog()
5913					<< tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
5914					<< ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
5915					<< expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
5916				status = false;
5917			}
5918		}
5919		for (int i = 32; i < 32 + 16; ++i)
5920		{
5921			if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
5922				fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
5923			{
5924				m_context.getTestContext().getLog()
5925					<< tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
5926					<< ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1] << ", "
5927					<< tcu::TestLog::EndMessage;
5928				status = false;
5929			}
5930		}
5931
5932		if (status)
5933			return NO_ERROR;
5934		else
5935			return ERROR;
5936	}
5937
5938	virtual long Cleanup()
5939	{
5940		glUseProgram(0);
5941		glDeleteProgram(m_program);
5942		glDeleteBuffers(5, m_storage_buffer);
5943		return NO_ERROR;
5944	}
5945};
5946//-----------------------------------------------------------------------------
5947// 2.4.2 AdvancedIndirectAddressingCase2
5948//-----------------------------------------------------------------------------
5949class AdvancedIndirectAddressingCase2VSFS : public ShaderStorageBufferObjectBase
5950{
5951	GLuint m_program;
5952	GLuint m_storage_buffer[8];
5953	GLuint m_vertex_array;
5954	GLuint m_vertex_buffer;
5955	GLuint m_fbo, m_rt;
5956
5957	virtual long Setup()
5958	{
5959		m_program = 0;
5960		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5961		m_vertex_array  = 0;
5962		m_vertex_buffer = 0;
5963		glGenFramebuffers(1, &m_fbo);
5964		glGenTextures(1, &m_rt);
5965		return NO_ERROR;
5966	}
5967
5968	virtual long Run()
5969	{
5970		if (!IsVSFSAvailable(4, 4))
5971			return NOT_SUPPORTED;
5972		GLint blocksC;
5973		glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
5974		if (blocksC < 8)
5975			return NOT_SUPPORTED;
5976		const char* const glsl_vs =
5977			NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
5978			   "  vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id;" NL "void main() {" NL
5979			   "  vec2 translation = vec2(0);" NL "  switch (g_transform_id) {" NL "  case 0u:" NL
5980			   "    translation = g_transform[0].translation;" NL "    break;" NL "  case 1u:" NL
5981			   "    translation = g_transform[1].translation;" NL "    break;" NL "  case 2u:" NL
5982			   "    translation = g_transform[2].translation;" NL "    break;" NL "  case 3u:" NL
5983			   "    translation = g_transform[3].translation;" NL "    break;" NL "  }" NL
5984			   "  gl_Position = vec4(g_in_position + translation, 0, 1);" NL "}";
5985		const char* const glsl_fs = NL
5986			"layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
5987			"  vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id;" NL "void main() {" NL
5988			"  vec3 color = vec3(0);" NL "  switch (g_material_id) {" NL "  case 0:" NL
5989			"    color = g_material[0].color;" NL "    break;" NL "  case 1:" NL "    color = g_material[1].color;" NL
5990			"    break;" NL "  case 2:" NL "    color = g_material[2].color;" NL "    break;" NL "  case 3:" NL
5991			"    color = g_material[3].color;" NL "    break;" NL "  }" NL "  g_fs_out = vec4(color, 1);" NL "}";
5992		m_program = CreateProgram(glsl_vs, glsl_fs);
5993		glLinkProgram(m_program);
5994		if (!CheckProgram(m_program))
5995			return ERROR;
5996
5997		glGenBuffers(8, m_storage_buffer);
5998
5999		/* transform buffers */
6000		{
6001			const float data[4][2] = { { -0.5f, -0.5f }, { 0.5f, -0.5f }, { -0.5f, 0.5f }, { 0.5f, 0.5f } };
6002			for (GLuint i = 0; i < 4; ++i)
6003			{
6004				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6005				glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6006			}
6007		}
6008		/* material buffers */
6009		{
6010			const float data[4][3] = {
6011				{ 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }
6012			};
6013			for (GLuint i = 0; i < 4; ++i)
6014			{
6015				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6016				glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6017			}
6018		}
6019
6020		/* vertex buffer */
6021		{
6022			const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
6023			glGenBuffers(1, &m_vertex_buffer);
6024			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6025			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6026			glBindBuffer(GL_ARRAY_BUFFER, 0);
6027		}
6028
6029		glBindTexture(GL_TEXTURE_2D, m_rt);
6030		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6031		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6032		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6033		glBindTexture(GL_TEXTURE_2D, 0);
6034		glViewport(0, 0, 100, 100);
6035		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6036		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6037
6038		glGenVertexArrays(1, &m_vertex_array);
6039		glBindVertexArray(m_vertex_array);
6040		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6041		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6042		glBindBuffer(GL_ARRAY_BUFFER, 0);
6043		glEnableVertexAttribArray(1);
6044		glBindVertexArray(0);
6045
6046		glUseProgram(m_program);
6047		glBindVertexArray(m_vertex_array);
6048
6049		glClear(GL_COLOR_BUFFER_BIT);
6050		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6051		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6052		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6053		if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6054		{
6055			return ERROR;
6056		}
6057
6058		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6059		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6060		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6061		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6062		{
6063			return ERROR;
6064		}
6065
6066		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6067		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6068		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6069		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6070		{
6071			return ERROR;
6072		}
6073
6074		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6075		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6076		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6077		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6078		{
6079			return ERROR;
6080		}
6081
6082		// once again with only one validation at the end
6083		glClear(GL_COLOR_BUFFER_BIT);
6084		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6085		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6086		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6087
6088		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6089		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6090		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6091
6092		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6093		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6094		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6095
6096		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6097		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6098		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6099		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6100
6101		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6102		{
6103			return ERROR;
6104		}
6105		return NO_ERROR;
6106	}
6107
6108	virtual long Cleanup()
6109	{
6110		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6111		glUseProgram(0);
6112		glDeleteProgram(m_program);
6113		glDeleteBuffers(8, m_storage_buffer);
6114		glDeleteBuffers(1, &m_vertex_buffer);
6115		glDeleteVertexArrays(1, &m_vertex_array);
6116		glDeleteFramebuffers(1, &m_fbo);
6117		glDeleteTextures(1, &m_rt);
6118		return NO_ERROR;
6119	}
6120};
6121
6122class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6123{
6124	GLuint m_program;
6125	GLuint m_storage_buffer[5];
6126
6127	virtual long Setup()
6128	{
6129		m_program = 0;
6130		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6131		return NO_ERROR;
6132	}
6133
6134	virtual long Run()
6135	{
6136		GLint blocksC;
6137		glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6138		if (blocksC < 8)
6139			return NOT_SUPPORTED;
6140		bool			  status = true;
6141		const char* const glsl_cs =
6142			NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL
6143			   "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL
6144			   "};" NL "uniform int g_material_id;" NL "void main() {" NL
6145			   "  if (g_material_id == 0) color[gl_LocalInvocationIndex] = g_material[0].color;" NL
6146			   "  else if (g_material_id == 1) color[gl_LocalInvocationIndex] = g_material[1].color;" NL
6147			   "  else if (g_material_id == 2) color[gl_LocalInvocationIndex] = g_material[2].color;" NL
6148			   "  else if (g_material_id == 3) color[gl_LocalInvocationIndex] = g_material[3].color;" NL "}";
6149		m_program = CreateProgramCS(glsl_cs);
6150		glLinkProgram(m_program);
6151		if (!CheckProgram(m_program))
6152			return ERROR;
6153
6154		glGenBuffers(5, m_storage_buffer);
6155
6156		/* material buffers */
6157		const float data[4][3] = {
6158			{ 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }
6159		};
6160		for (GLuint i = 0; i < 4; ++i)
6161		{
6162			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6163			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6164		}
6165
6166		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6167		glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6168
6169		glUseProgram(m_program);
6170		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6171		glDispatchCompute(1, 1, 1);
6172		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6173		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6174		GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6175		if (!out_data)
6176			return ERROR;
6177		const float* expected = &data[1][0];
6178		for (int i = 0; i < 4; ++i)
6179		{
6180			if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6181				out_data[i * 4 + 2] != expected[2])
6182			{
6183				m_context.getTestContext().getLog()
6184					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6185					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6186					<< expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << ", " << tcu::TestLog::EndMessage;
6187				status = false;
6188			}
6189		}
6190		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6191		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6192		glDispatchCompute(1, 1, 1);
6193		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6194		out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6195		if (!out_data)
6196			return ERROR;
6197		expected = &data[3][0];
6198		for (int i = 0; i < 4; ++i)
6199		{
6200			if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6201				out_data[i * 4 + 2] != expected[2])
6202			{
6203				m_context.getTestContext().getLog()
6204					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6205					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6206					<< expected[2] << ", " << tcu::TestLog::EndMessage;
6207				status = false;
6208			}
6209		}
6210
6211		if (!status)
6212		{
6213			return ERROR;
6214		}
6215		return NO_ERROR;
6216	}
6217
6218	virtual long Cleanup()
6219	{
6220		glUseProgram(0);
6221		glDeleteProgram(m_program);
6222		glDeleteBuffers(5, m_storage_buffer);
6223		return NO_ERROR;
6224	}
6225};
6226
6227//-----------------------------------------------------------------------------
6228// 2.5.1 AdvancedReadWriteCase1
6229//-----------------------------------------------------------------------------
6230class AdvancedReadWriteCase1VSFS : public ShaderStorageBufferObjectBase
6231{
6232	GLuint m_program;
6233	GLuint m_storage_buffer;
6234	GLuint m_vertex_array;
6235	GLuint m_vertex_buffer;
6236
6237	virtual long Setup()
6238	{
6239		m_program		 = 0;
6240		m_storage_buffer = 0;
6241		m_vertex_array   = 0;
6242		m_vertex_buffer  = 0;
6243		return NO_ERROR;
6244	}
6245
6246	virtual long Run()
6247	{
6248		if (!IsVSFSAvailable(1, 1))
6249			return NOT_SUPPORTED;
6250		const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6251									   "  vec4 in_color;" NL "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6252									   "  if (gl_VertexID == 0) {" NL "    g_buffer.out_color = g_buffer.in_color;" NL
6253									   "    memoryBarrier();" NL "  }" NL "  gl_Position = g_in_position;" NL "}";
6254		const char* const glsl_fs =
6255			NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL "  vec4 in_color;" NL
6256			   "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL "  g_fs_out = g_buffer.out_color;" NL "}";
6257		m_program = CreateProgram(glsl_vs, glsl_fs);
6258		glLinkProgram(m_program);
6259		if (!CheckProgram(m_program))
6260			return ERROR;
6261
6262		glGenBuffers(1, &m_storage_buffer);
6263		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6264		glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6265		float* ptr = reinterpret_cast<float*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_WRITE_BIT));
6266		if (!ptr)
6267			return ERROR;
6268		*ptr++ = 0.0f;
6269		*ptr++ = 1.0f;
6270		*ptr++ = 0.0f;
6271		*ptr++ = 1.0f;
6272		*ptr++ = 0.0f;
6273		*ptr++ = 0.0f;
6274		*ptr++ = 0.0f;
6275		*ptr++ = 0.0f;
6276		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6277
6278		/* vertex buffer */
6279		{
6280			const float data[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
6281			glGenBuffers(1, &m_vertex_buffer);
6282			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6283			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6284			glBindBuffer(GL_ARRAY_BUFFER, 0);
6285		}
6286
6287		glGenVertexArrays(1, &m_vertex_array);
6288		glBindVertexArray(m_vertex_array);
6289		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6290		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6291		glBindBuffer(GL_ARRAY_BUFFER, 0);
6292		glEnableVertexAttribArray(0);
6293		glBindVertexArray(0);
6294
6295		glClear(GL_COLOR_BUFFER_BIT);
6296		glUseProgram(m_program);
6297		glBindVertexArray(m_vertex_array);
6298		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6299		if (!CheckFB(vec3(0, 1, 0)))
6300		{
6301			return ERROR;
6302		}
6303
6304		ptr = reinterpret_cast<float*>(
6305			glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6306		if (!ptr)
6307			return ERROR;
6308		*ptr++ = 1.0f;
6309		*ptr++ = 0.0f;
6310		*ptr++ = 1.0f;
6311		*ptr++ = 1.0f;
6312		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6313
6314		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6315		if (!CheckFB(vec3(1, 0, 1)))
6316		{
6317			return ERROR;
6318		}
6319
6320		return NO_ERROR;
6321	}
6322
6323	virtual long Cleanup()
6324	{
6325		glUseProgram(0);
6326		glDeleteProgram(m_program);
6327		glDeleteBuffers(1, &m_storage_buffer);
6328		glDeleteBuffers(1, &m_vertex_buffer);
6329		glDeleteVertexArrays(1, &m_vertex_array);
6330		return NO_ERROR;
6331	}
6332};
6333class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6334{
6335	GLuint m_program;
6336	GLuint m_storage_buffer;
6337
6338	virtual long Setup()
6339	{
6340		m_program		 = 0;
6341		m_storage_buffer = 0;
6342		return NO_ERROR;
6343	}
6344
6345	virtual long Run()
6346	{
6347		bool			  status  = true;
6348		const char* const glsl_cs = NL
6349			"layout(local_size_x = 128) in;" NL "struct s {" NL "  int ene;" NL "  int due;" NL "  int like;" NL
6350			"  int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL "  s a[128];" NL "} g_buffer;" NL
6351			"void main() {" NL "  g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6352			"  groupMemoryBarrier();" NL "  barrier();" NL "  g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6353			"g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL "  groupMemoryBarrier();" NL "  barrier();" NL
6354			"  g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6355			"= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6356			"128u].like;" NL "}";
6357		m_program = CreateProgramCS(glsl_cs);
6358		glLinkProgram(m_program);
6359		if (!CheckProgram(m_program))
6360			return ERROR;
6361
6362		glGenBuffers(1, &m_storage_buffer);
6363		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6364		GLint data[128 * 4];
6365		for (int i = 0; i < 128; ++i)
6366		{
6367			data[i * 4]		= i + 256;
6368			data[i * 4 + 1] = 0;
6369			data[i * 4 + 2] = 0;
6370			data[i * 4 + 3] = 0;
6371		}
6372		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6373
6374		glUseProgram(m_program);
6375		glDispatchCompute(1, 1, 1);
6376		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6377		GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6378		if (!out_data)
6379			return ERROR;
6380		for (int i = 0; i < 128; ++i)
6381		{
6382			if (out_data[i * 4 + 3] != data[i * 4])
6383			{
6384				m_context.getTestContext().getLog()
6385					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", but expected: " << data[i * 4]
6386					<< " -> " << out_data[i * 4 + 1] << " -> " << out_data[i * 4 + 2] << " -> "
6387					<< tcu::TestLog::EndMessage;
6388				status = false;
6389			}
6390		}
6391		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6392		for (int i = 0; i < 128; ++i)
6393		{
6394			data[i * 4]		= i + 512;
6395			data[i * 4 + 1] = 0;
6396			data[i * 4 + 2] = 0;
6397			data[i * 4 + 3] = 0;
6398		}
6399		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6400
6401		glDispatchCompute(1, 1, 1);
6402		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6403		out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6404		if (!out_data)
6405			return ERROR;
6406		for (int i = 0; i < 128; ++i)
6407		{
6408			if (out_data[i * 4 + 3] != data[i * 4])
6409			{
6410				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3]
6411													<< ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6412				status = false;
6413			}
6414		}
6415		if (status)
6416			return NO_ERROR;
6417		else
6418			return ERROR;
6419	}
6420
6421	virtual long Cleanup()
6422	{
6423		glUseProgram(0);
6424		glDeleteProgram(m_program);
6425		glDeleteBuffers(1, &m_storage_buffer);
6426		return NO_ERROR;
6427	}
6428};
6429//-----------------------------------------------------------------------------
6430// 2.6.1 AdvancedUsageCase1
6431//-----------------------------------------------------------------------------
6432class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6433{
6434	GLuint m_program;
6435	GLuint m_storage_buffer[3];
6436	GLuint m_vertex_array;
6437	GLuint m_vertex_buffer;
6438	GLuint m_fbo, m_rt;
6439
6440	virtual long Setup()
6441	{
6442		m_program = 0;
6443		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6444		m_vertex_array  = 0;
6445		m_vertex_buffer = 0;
6446		glGenFramebuffers(1, &m_fbo);
6447		glGenTextures(1, &m_rt);
6448		return NO_ERROR;
6449	}
6450
6451	virtual long Run()
6452	{
6453		if (!IsVSFSAvailable(2, 2))
6454			return NOT_SUPPORTED;
6455		const char* const glsl_vs =
6456			NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
6457			   "flat out int object_id;" NL "layout(binding = 0) buffer TransformBuffer {" NL
6458			   "  mat4 g_transform[4];" NL "};" NL "void main() {" NL "  mat4 mvp = g_transform[g_object_id];" NL
6459			   "  gl_Position = mvp * g_position;" NL "  object_id = g_object_id;" NL "}";
6460		const char* const glsl_fs =
6461			NL "flat in int object_id;" NL "layout(location = 0) out vec4 g_fs_out;" NL "struct Material {" NL
6462			   "  vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
6463			   "  Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
6464			   "  int g_material_id[4];" NL "};" NL "void main() {" NL "  int mid = g_material_id[object_id];" NL
6465			   "  Material m = g_material[mid];" NL "  g_fs_out = vec4(m.color, 1);" NL "}";
6466		m_program = CreateProgram(glsl_vs, glsl_fs);
6467		glLinkProgram(m_program);
6468		if (!CheckProgram(m_program))
6469			return ERROR;
6470
6471		glGenBuffers(3, m_storage_buffer);
6472
6473		/* transform buffer */
6474		{
6475			mat4 data[] = { Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
6476							Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f) };
6477			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6478			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6479		}
6480		/* material buffer */
6481		{
6482			vec4 data[] = { vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1) };
6483			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6484			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6485		}
6486		/* material id buffer */
6487		{
6488			int data[] = { 0, 1, 2, 3 };
6489			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6490			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6491		}
6492		/* vertex buffer */
6493		{
6494			struct
6495			{
6496				vec2 position;
6497				int  object_id;
6498			} data[] = { { vec2(-0.4f, -0.4f), 0 }, { vec2(0.4f, -0.4f), 0 },  { vec2(-0.4f, 0.4f), 0 },
6499						 { vec2(0.4f, 0.4f), 0 },   { vec2(-0.4f, -0.4f), 1 }, { vec2(0.4f, -0.4f), 1 },
6500						 { vec2(-0.4f, 0.4f), 1 },  { vec2(0.4f, 0.4f), 1 },   { vec2(-0.4f, -0.4f), 2 },
6501						 { vec2(0.4f, -0.4f), 2 },  { vec2(-0.4f, 0.4f), 2 },  { vec2(0.4f, 0.4f), 2 },
6502						 { vec2(-0.4f, -0.4f), 3 }, { vec2(0.4f, -0.4f), 3 },  { vec2(-0.4f, 0.4f), 3 },
6503						 { vec2(0.4f, 0.4f), 3 } };
6504			glGenBuffers(1, &m_vertex_buffer);
6505			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6506			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6507			glBindBuffer(GL_ARRAY_BUFFER, 0);
6508		}
6509
6510		glBindTexture(GL_TEXTURE_2D, m_rt);
6511		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6512		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6513		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6514		glBindTexture(GL_TEXTURE_2D, 0);
6515		glViewport(0, 0, 100, 100);
6516		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6517		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
6518
6519		glGenVertexArrays(1, &m_vertex_array);
6520		glBindVertexArray(m_vertex_array);
6521		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6522		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
6523		glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void*>(sizeof(vec2)));
6524		glBindBuffer(GL_ARRAY_BUFFER, 0);
6525		glEnableVertexAttribArray(0);
6526		glEnableVertexAttribArray(1);
6527		glBindVertexArray(0);
6528
6529		glClear(GL_COLOR_BUFFER_BIT);
6530		glUseProgram(m_program);
6531		glBindVertexArray(m_vertex_array);
6532		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6533		glDrawArrays(GL_TRIANGLE_STRIP, 4, 4);
6534		glDrawArrays(GL_TRIANGLE_STRIP, 8, 4);
6535		glDrawArrays(GL_TRIANGLE_STRIP, 12, 4);
6536		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
6537		{
6538			return ERROR;
6539		}
6540		return NO_ERROR;
6541	}
6542
6543	virtual long Cleanup()
6544	{
6545		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6546		glUseProgram(0);
6547		glDeleteProgram(m_program);
6548		glDeleteBuffers(3, m_storage_buffer);
6549		glDeleteBuffers(1, &m_vertex_buffer);
6550		glDeleteVertexArrays(1, &m_vertex_array);
6551		glDeleteFramebuffers(1, &m_fbo);
6552		glDeleteTextures(1, &m_rt);
6553		return NO_ERROR;
6554	}
6555};
6556
6557//-----------------------------------------------------------------------------
6558// 2.6.2 AdvancedUsageSync
6559//-----------------------------------------------------------------------------
6560class AdvancedUsageSyncVSFS : public ShaderStorageBufferObjectBase
6561{
6562	GLuint m_program;
6563	GLuint m_storage_buffer[7];
6564	GLuint m_vertex_array;
6565
6566	virtual long Setup()
6567	{
6568		m_program = 0;
6569		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6570		m_vertex_array = 0;
6571		return NO_ERROR;
6572	}
6573
6574	virtual long Run()
6575	{
6576		if (!IsVSFSAvailable(3, 4))
6577			return NOT_SUPPORTED;
6578		const char* const glsl_vs = NL
6579			"layout(std430, binding = 0) coherent buffer Buffer0 {" NL "  int g_data0, g_inc0;" NL
6580			"  int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL
6581			"} g_buffer12[2];" NL "flat out int primitive_id;" NL NL "void Modify(int path) {" NL
6582			"  if (path == 0) {" NL "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL
6583			"  } else if (path == 1) {" NL "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
6584			"  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
6585			"  }" NL NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
6586			"  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
6587			"void main() {" NL "  Modify(gl_VertexID);" NL "  primitive_id = gl_VertexID;" NL
6588			"  gl_Position = vec4(0, 0, 0, 1);" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL "}";
6589		const char* glsl_fs =
6590			NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
6591			   "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
6592			   "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6593			   "  int inc, data;" NL "} g_buffer56[2];" NL "flat in int primitive_id;" NL NL
6594			   "void ModifyFS(int path) {" NL "  if (path == 0) {" NL
6595			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6596			   "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6597			   "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
6598			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6599			   "  }" NL NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
6600			   "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL
6601			   "void main() {" NL "  atomicAdd(g_buffer3.data, 1);" NL "  ModifyFS(primitive_id);" NL "}";
6602		m_program = CreateProgram(glsl_vs, glsl_fs);
6603		glLinkProgram(m_program);
6604		if (!CheckProgram(m_program))
6605			return ERROR;
6606
6607		glGenVertexArrays(1, &m_vertex_array);
6608		glGenBuffers(7, m_storage_buffer);
6609
6610		/* Buffer0 */
6611		{
6612			int data[4] = { 0, 1, 0, 2 };
6613			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6614			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6615		}
6616		/* Buffer1 */
6617		{
6618			int data[2] = { 3, 1 };
6619			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6620			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6621		}
6622		/* Buffer2 */
6623		{
6624			int data[2] = { 2, 4 };
6625			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6626			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6627		}
6628		/* Buffer3 */
6629		{
6630			int data[1] = { 0 };
6631			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6632			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6633		}
6634		/* Buffer4 */
6635		{
6636			int data[4] = { 0, 1, 0, 2 };
6637			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6638			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6639		}
6640		/* Buffer5 */
6641		{
6642			int data[2] = { 3, 1 };
6643			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6644			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6645		}
6646		/* Buffer6 */
6647		{
6648			int data[2] = { 2, 4 };
6649			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6650			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6651		}
6652
6653		glUseProgram(m_program);
6654		glBindVertexArray(m_vertex_array);
6655
6656		glDrawArrays(GL_POINTS, 0, 3);
6657		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6658		glDrawArrays(GL_POINTS, 0, 3);
6659		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6660
6661		/* Buffer0 */
6662		{
6663			const int ref_data[4] = { 4, 1, 4, 2 };
6664			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6665			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6666			if (!data)
6667				return ERROR;
6668			for (int i = 0; i < 4; ++i)
6669			{
6670				if (data[i] != ref_data[i])
6671				{
6672					m_context.getTestContext().getLog()
6673						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6674						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6675					return ERROR;
6676				}
6677			}
6678			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6679		}
6680		/* Buffer1 */
6681		{
6682			const int ref_data[2] = { 3, 5 };
6683			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6684			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6685			if (!data)
6686				return ERROR;
6687			for (int i = 0; i < 2; ++i)
6688			{
6689				if (data[i] != ref_data[i])
6690				{
6691					m_context.getTestContext().getLog()
6692						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6693						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6694					return ERROR;
6695				}
6696			}
6697			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6698		}
6699		/* Buffer2 */
6700		{
6701			const int ref_data[2] = { 2, 10 };
6702			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6703			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6704			if (!data)
6705				return ERROR;
6706			for (int i = 0; i < 2; ++i)
6707			{
6708				if (data[i] != ref_data[i])
6709				{
6710					m_context.getTestContext().getLog()
6711						<< tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6712						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6713					return ERROR;
6714				}
6715			}
6716			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6717		}
6718		/* Buffer3 */
6719		{
6720			const int ref_data[1] = { 6 };
6721			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6722			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6723			if (!data)
6724				return ERROR;
6725			for (int i = 0; i < 1; ++i)
6726			{
6727				if (data[i] != ref_data[i])
6728				{
6729					m_context.getTestContext().getLog()
6730						<< tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6731						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6732					return ERROR;
6733				}
6734			}
6735			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6736		}
6737		/* Buffer4 */
6738		{
6739			const int ref_data[4] = { 4, 1, 4, 2 };
6740			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6741			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6742			if (!data)
6743				return ERROR;
6744			for (int i = 0; i < 4; ++i)
6745			{
6746				if (data[i] != ref_data[i])
6747				{
6748					m_context.getTestContext().getLog()
6749						<< tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6750						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6751					return ERROR;
6752				}
6753			}
6754			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6755		}
6756		/* Buffer5 */
6757		{
6758			const int ref_data[2] = { 3, 5 };
6759			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
6760			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6761			if (!data)
6762				return ERROR;
6763			for (int i = 0; i < 2; ++i)
6764			{
6765				if (data[i] != ref_data[i])
6766				{
6767					m_context.getTestContext().getLog()
6768						<< tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
6769						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6770					return ERROR;
6771				}
6772			}
6773			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6774		}
6775		/* Buffer6 */
6776		{
6777			const int ref_data[2] = { 2, 10 };
6778			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
6779			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6780			if (!data)
6781				return ERROR;
6782			for (int i = 0; i < 2; ++i)
6783			{
6784				if (data[i] != ref_data[i])
6785				{
6786					m_context.getTestContext().getLog()
6787						<< tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
6788						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6789					return ERROR;
6790				}
6791			}
6792			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6793		}
6794
6795		return NO_ERROR;
6796	}
6797
6798	virtual long Cleanup()
6799	{
6800		glUseProgram(0);
6801		glDeleteProgram(m_program);
6802		glDeleteBuffers(7, m_storage_buffer);
6803		glDeleteVertexArrays(1, &m_vertex_array);
6804		return NO_ERROR;
6805	}
6806};
6807class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
6808{
6809	GLuint m_program;
6810	GLuint m_storage_buffer[7];
6811
6812	virtual long Setup()
6813	{
6814		m_program = 0;
6815		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6816		return NO_ERROR;
6817	}
6818
6819	virtual long Run()
6820	{
6821		const char* const glsl_cs =
6822			NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
6823			   "  int g_data0, g_inc0;" NL "  int g_data1, g_inc1;" NL "};" NL
6824			   "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL "} g_buffer12[2];" NL
6825			   "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
6826			   "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
6827			   "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
6828			   "  int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL "  if (path == 0) {" NL
6829			   "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
6830			   "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
6831			   "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
6832			   "  }" NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
6833			   "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
6834			   "void Modify2(int path) {" NL "  if (path == 0) {" NL
6835			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
6836			   "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
6837			   "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
6838			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
6839			   "  }" NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
6840			   "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL NL
6841			   "void main() {" NL "  Modify1(int(gl_WorkGroupID.z));" NL "  atomicAdd(g_buffer3.data, 1);" NL
6842			   "  Modify2(int(gl_WorkGroupID.z));" NL "}";
6843		m_program = CreateProgramCS(glsl_cs);
6844		glLinkProgram(m_program);
6845		if (!CheckProgram(m_program))
6846			return ERROR;
6847
6848		glGenBuffers(7, m_storage_buffer);
6849
6850		/* Buffer0 */
6851		{
6852			int data[4] = { 0, 1, 0, 2 };
6853			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6854			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6855		}
6856		/* Buffer1 */
6857		{
6858			int data[2] = { 3, 1 };
6859			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6860			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6861		}
6862		/* Buffer2 */
6863		{
6864			int data[2] = { 2, 4 };
6865			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6866			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6867		}
6868		/* Buffer3 */
6869		{
6870			int data[1] = { 0 };
6871			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6872			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6873		}
6874		/* Buffer4 */
6875		{
6876			int data[4] = { 0, 1, 0, 2 };
6877			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6878			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6879		}
6880		/* Buffer5 */
6881		{
6882			int data[2] = { 3, 1 };
6883			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
6884			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6885		}
6886		/* Buffer6 */
6887		{
6888			int data[2] = { 2, 4 };
6889			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
6890			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
6891		}
6892
6893		glUseProgram(m_program);
6894
6895		glDispatchCompute(1, 1, 3);
6896		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
6897		glDispatchCompute(1, 1, 3);
6898
6899		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6900
6901		/* Buffer0 */
6902		{
6903			const int ref_data[4] = { 4, 1, 4, 2 };
6904			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
6905			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6906			if (!data)
6907				return ERROR;
6908			for (int i = 0; i < 4; ++i)
6909			{
6910				if (data[i] != ref_data[i])
6911				{
6912					m_context.getTestContext().getLog()
6913						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
6914						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6915					return ERROR;
6916				}
6917			}
6918			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6919		}
6920		/* Buffer1 */
6921		{
6922			const int ref_data[2] = { 3, 5 };
6923			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6924			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6925			if (!data)
6926				return ERROR;
6927			for (int i = 0; i < 2; ++i)
6928			{
6929				if (data[i] != ref_data[i])
6930				{
6931					m_context.getTestContext().getLog()
6932						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
6933						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6934					return ERROR;
6935				}
6936			}
6937			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6938		}
6939		/* Buffer2 */
6940		{
6941			const int ref_data[2] = { 2, 10 };
6942			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
6943			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
6944			if (!data)
6945				return ERROR;
6946			for (int i = 0; i < 2; ++i)
6947			{
6948				if (data[i] != ref_data[i])
6949				{
6950					m_context.getTestContext().getLog()
6951						<< tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
6952						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6953					return ERROR;
6954				}
6955			}
6956			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6957		}
6958		/* Buffer3 */
6959		{
6960			const int ref_data[1] = { 6 };
6961			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6962			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
6963			if (!data)
6964				return ERROR;
6965			for (int i = 0; i < 1; ++i)
6966			{
6967				if (data[i] != ref_data[i])
6968				{
6969					m_context.getTestContext().getLog()
6970						<< tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
6971						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6972					return ERROR;
6973				}
6974			}
6975			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6976		}
6977		/* Buffer4 */
6978		{
6979			const int ref_data[4] = { 4, 1, 4, 2 };
6980			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6981			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
6982			if (!data)
6983				return ERROR;
6984			for (int i = 0; i < 4; ++i)
6985			{
6986				if (data[i] != ref_data[i])
6987				{
6988					m_context.getTestContext().getLog()
6989						<< tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
6990						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
6991					return ERROR;
6992				}
6993			}
6994			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6995		}
6996		/* Buffer5 */
6997		{
6998			const int ref_data[2] = { 3, 5 };
6999			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7000			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7001			if (!data)
7002				return ERROR;
7003			for (int i = 0; i < 2; ++i)
7004			{
7005				if (data[i] != ref_data[i])
7006				{
7007					m_context.getTestContext().getLog()
7008						<< tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7009						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7010					return ERROR;
7011				}
7012			}
7013			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7014		}
7015		/* Buffer6 */
7016		{
7017			const int ref_data[2] = { 2, 10 };
7018			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7019			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7020			if (!data)
7021				return ERROR;
7022			for (int i = 0; i < 2; ++i)
7023			{
7024				if (data[i] != ref_data[i])
7025				{
7026					m_context.getTestContext().getLog()
7027						<< tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7028						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7029					return ERROR;
7030				}
7031			}
7032			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7033		}
7034
7035		return NO_ERROR;
7036	}
7037
7038	virtual long Cleanup()
7039	{
7040		glUseProgram(0);
7041		glDeleteProgram(m_program);
7042		glDeleteBuffers(7, m_storage_buffer);
7043		return NO_ERROR;
7044	}
7045};
7046//-----------------------------------------------------------------------------
7047// 2.6.3 AdvancedUsageOperators
7048//-----------------------------------------------------------------------------
7049class AdvancedUsageOperatorsVS : public ShaderStorageBufferObjectBase
7050{
7051	GLuint m_program;
7052	GLuint m_storage_buffer[2];
7053	GLuint m_vertex_array;
7054
7055	virtual long Setup()
7056	{
7057		m_program = 0;
7058		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7059		m_vertex_array = 0;
7060		return NO_ERROR;
7061	}
7062
7063	virtual long Run()
7064	{
7065		if (!IsVSFSAvailable(2, 0))
7066			return NOT_SUPPORTED;
7067		const char* const glsl_vs =
7068			NL "layout(std430, binding = 0) buffer Buffer0 {" NL "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL
7069			   "layout(std430, binding = 1) buffer Buffer1 {" NL "  int i0;" NL "} g_buffer1;" NL
7070			   "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL "  g_o0 += g_i0;" NL
7071			   "  g_o0 <<= 1;" NL "  g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL "  g_o0 *= g_i0;" NL
7072			   "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7073			   "  g_o0 &= g_buffer1.i0;" NL "}";
7074		const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7075									   "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
7076
7077		m_program = CreateProgram(glsl_vs, glsl_fs);
7078		glLinkProgram(m_program);
7079		if (!CheckProgram(m_program))
7080			return ERROR;
7081
7082		glGenVertexArrays(1, &m_vertex_array);
7083		glGenBuffers(2, m_storage_buffer);
7084
7085		/* Buffer0 */
7086		{
7087			int data[4] = { 3, 5 };
7088			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7089			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7090		}
7091		/* Buffer1 */
7092		{
7093			int data[1] = { 0 };
7094			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7095			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7096		}
7097
7098		glEnable(GL_RASTERIZER_DISCARD);
7099		glUseProgram(m_program);
7100		glBindVertexArray(m_vertex_array);
7101		glDrawArrays(GL_POINTS, 0, 1);
7102		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7103
7104		/* Buffer0 */
7105		{
7106			const int ref_data[2] = { 3, 37 };
7107			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7108			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7109			if (!data)
7110				return ERROR;
7111			for (int i = 0; i < 2; ++i)
7112			{
7113				if (data[i] != ref_data[i])
7114				{
7115					m_context.getTestContext().getLog()
7116						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7117						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7118					return ERROR;
7119				}
7120			}
7121			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7122		}
7123		/* Buffer0 */
7124		{
7125			const int ref_data[1] = { 0xff2f };
7126			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7127			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7128			if (!data)
7129				return ERROR;
7130			for (int i = 0; i < 1; ++i)
7131			{
7132				if (data[i] != ref_data[i])
7133				{
7134					m_context.getTestContext().getLog()
7135						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7136						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7137					return ERROR;
7138				}
7139			}
7140			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7141		}
7142
7143		return NO_ERROR;
7144	}
7145
7146	virtual long Cleanup()
7147	{
7148		glDisable(GL_RASTERIZER_DISCARD);
7149		glUseProgram(0);
7150		glDeleteProgram(m_program);
7151		glDeleteBuffers(2, m_storage_buffer);
7152		glDeleteVertexArrays(1, &m_vertex_array);
7153		return NO_ERROR;
7154	}
7155};
7156class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7157{
7158	GLuint m_program;
7159	GLuint m_storage_buffer[2];
7160
7161	virtual long Setup()
7162	{
7163		m_program = 0;
7164		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7165		return NO_ERROR;
7166	}
7167
7168	virtual long Run()
7169	{
7170		const char* const glsl_cs =
7171			NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7172			   "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7173			   "  int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7174			   "  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
7175			   "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7176			   "  g_o0 &= g_buffer1.i0;" NL "}";
7177
7178		m_program = CreateProgramCS(glsl_cs);
7179		glLinkProgram(m_program);
7180		if (!CheckProgram(m_program))
7181			return ERROR;
7182
7183		glGenBuffers(2, m_storage_buffer);
7184
7185		/* Buffer0 */
7186		{
7187			int data[4] = { 3, 5 };
7188			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7189			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7190		}
7191		/* Buffer1 */
7192		{
7193			int data[1] = { 0 };
7194			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7195			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7196		}
7197
7198		glUseProgram(m_program);
7199		glDispatchCompute(1, 1, 1);
7200		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7201
7202		/* Buffer0 */
7203		{
7204			const int ref_data[2] = { 3, 37 };
7205			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7206			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7207			if (!data)
7208				return ERROR;
7209			for (int i = 0; i < 2; ++i)
7210			{
7211				if (data[i] != ref_data[i])
7212				{
7213					m_context.getTestContext().getLog()
7214						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7215						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7216					return ERROR;
7217				}
7218			}
7219			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7220		}
7221
7222		return NO_ERROR;
7223	}
7224
7225	virtual long Cleanup()
7226	{
7227		glUseProgram(0);
7228		glDeleteProgram(m_program);
7229		glDeleteBuffers(2, m_storage_buffer);
7230		return NO_ERROR;
7231	}
7232};
7233
7234//-----------------------------------------------------------------------------
7235// 2.7 AdvancedUnsizedArrayLength
7236//-----------------------------------------------------------------------------
7237template <int stage>
7238class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7239{
7240	GLuint m_program;
7241	GLuint m_storage_buffer[4];
7242	GLuint m_vertex_array;
7243
7244	virtual long Setup()
7245	{
7246		m_program = 0;
7247		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7248		m_vertex_array = 0;
7249		return NO_ERROR;
7250	}
7251
7252	virtual long Cleanup()
7253	{
7254		glUseProgram(0);
7255		glDeleteProgram(m_program);
7256		glDeleteBuffers(4, m_storage_buffer);
7257		if (stage != compute)
7258			glDeleteVertexArrays(1, &m_vertex_array);
7259		return NO_ERROR;
7260	}
7261	std::string BuildShaderPT(int st)
7262	{
7263		std::ostringstream os;
7264		if (st == vertex)
7265		{
7266			os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7267					 "  gl_PointSize = 1.0f;" NL "#endif";
7268		}
7269		if (st == fragment)
7270		{
7271			os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7272					 "  o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7273		}
7274		os << NL "}";
7275		return os.str();
7276	}
7277	std::string BuildShader()
7278	{
7279		std::ostringstream os;
7280		std::string		   decl =
7281			NL "layout(std430, binding = 0) readonly buffer Input0 {" NL "  uint g_input0[];" NL "};" NL
7282			   "layout(std430, binding = 1) readonly buffer Input23 {" NL "  float data[];" NL "} g_input23[2];" NL
7283			   "layout(std430, binding = 3) buffer Output {" NL "  int g_length2;" NL "  int g_length[];" NL "};";
7284		std::string expr = NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input23[0].data.length();" NL
7285							  "  g_length[2] = g_input23[1].data.length();" NL "  g_length2 = g_length.length();";
7286		if (stage == vertex)
7287		{
7288			os << decl << NL "void main() {" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL
7289							 "  gl_Position = vec4(0,0,0,1);"
7290			   << expr;
7291		}
7292		if (stage == fragment)
7293		{
7294			os << NL "layout(location = 0) out vec4 o_color;" << decl
7295			   << NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7296		}
7297		if (stage == compute)
7298		{
7299			os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7300		}
7301		os << NL "}";
7302		return os.str();
7303	}
7304
7305	virtual long Run()
7306	{
7307		const int kSize = 10000;
7308		const int kBufs = 4;
7309		if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7310			return NOT_SUPPORTED;
7311		if (stage == vertex)
7312		{
7313			std::string glsl_vs = BuildShader();
7314			std::string glsl_fs = BuildShaderPT(fragment);
7315			m_program			= CreateProgram(glsl_vs, glsl_fs);
7316		}
7317		else if (stage == fragment)
7318		{
7319			std::string glsl_vs = BuildShaderPT(vertex);
7320			std::string glsl_fs = BuildShader();
7321			m_program			= CreateProgram(glsl_vs, glsl_fs);
7322		}
7323		else
7324		{ // compute
7325			std::string glsl_cs = BuildShader();
7326			m_program			= CreateProgramCS(glsl_cs);
7327		}
7328		glLinkProgram(m_program);
7329		if (!CheckProgram(m_program))
7330			return ERROR;
7331		glUseProgram(m_program);
7332
7333		glGenBuffers(kBufs, m_storage_buffer);
7334		int				 sizes[kBufs] = { 7, 3, 4, 5 };
7335		std::vector<int> data(kSize, 41);
7336		for (int i = 0; i < kBufs; ++i)
7337		{
7338			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7339			glBufferData(GL_SHADER_STORAGE_BUFFER, sizes[i] * 4, &data[0], GL_DYNAMIC_COPY);
7340		}
7341
7342		if (stage != compute)
7343		{
7344			glGenVertexArrays(1, &m_vertex_array);
7345			glBindVertexArray(m_vertex_array);
7346			glDrawArrays(GL_POINTS, 0, 1);
7347		}
7348		else
7349		{
7350			glDispatchCompute(1, 1, 1);
7351		}
7352		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7353
7354		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7355		int* dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7356		if (!dataout)
7357			return ERROR;
7358		bool status = true;
7359		for (int i = 0; i < kBufs - 1; ++i)
7360			if (dataout[i + 1] != sizes[i])
7361			{
7362				m_context.getTestContext().getLog()
7363					<< tcu::TestLog::Message << "Array " << i << " length is " << dataout[i + 1] << " should be "
7364					<< sizes[i] << tcu::TestLog::EndMessage;
7365				status = false;
7366			}
7367		if (dataout[0] != sizes[kBufs - 1] - 1)
7368		{
7369			m_context.getTestContext().getLog()
7370				<< tcu::TestLog::Message << "Array " << (kBufs - 1) << " length is " << dataout[0] << " should be "
7371				<< (sizes[kBufs - 1] - 1) << tcu::TestLog::EndMessage;
7372			status = false;
7373		}
7374		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7375
7376		if (!status)
7377			return ERROR;
7378
7379		return NO_ERROR;
7380	}
7381};
7382
7383class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7384{
7385	GLuint		 m_program;
7386	GLuint		 m_storage_buffer[8];
7387	GLuint		 m_vertex_array;
7388	virtual void SetPath() = 0;
7389
7390	virtual long Setup()
7391	{
7392		m_program = 0;
7393		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7394		m_vertex_array = 0;
7395		return NO_ERROR;
7396	}
7397
7398	virtual long Cleanup()
7399	{
7400		glUseProgram(0);
7401		glDeleteProgram(m_program);
7402		glDeleteBuffers(8, m_storage_buffer);
7403		if (stage != compute)
7404			glDeleteVertexArrays(1, &m_vertex_array);
7405		return NO_ERROR;
7406	}
7407	std::string BuildShaderPT(int stagept)
7408	{
7409		std::ostringstream os;
7410		if (stagept == vertex)
7411		{
7412			os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" NL "#ifdef GL_ES" NL
7413					 "  gl_PointSize = 1.0f;" NL "#endif";
7414		}
7415		if (stagept == fragment)
7416		{
7417			os << NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
7418					 "  o_color = vec4(0.0, 1.0, 0.0, 1.0);";
7419		}
7420		os << NL "}";
7421		return os.str();
7422	}
7423	std::string BuildShader()
7424	{
7425		std::ostringstream os;
7426		std::string		   e[4][7] = { { "bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4" },
7427								{ "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7428								{ "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7429								{ "S0", "S1", "S2", "S2", "S4", "S5", "S6" } };
7430		std::string sd =
7431			NL "struct S0 {" NL "  float f;" NL "  int i;" NL "  uint ui;" NL "  bool b;" NL "};" NL "struct S1 {" NL
7432			   "  ivec3 iv;" NL "  bvec2 bv;" NL "  vec4 v;" NL "  uvec2 uv;" NL "};" NL "struct S2 {" NL
7433			   "  mat2x2 m22;" NL "  mat4x4 m44;" NL "  mat2x3 m23;" NL "  mat4x2 m42;" NL "  mat3x4 m34;" NL "};" NL
7434			   "struct S4 {" NL "  float f[1];" NL "  int i[2];" NL "  uint ui[3];" NL "  bool b[4];" NL
7435			   "  ivec3 iv[5];" NL "  bvec2 bv[6];" NL "  vec4  v[7];" NL "  uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7436			   "  S0 s0;" NL "  S1 s1;" NL "  S2 s2;" NL "};" NL "struct S6 {" NL "  S4 s4[3];" NL "};";
7437
7438		std::string lo   = "";
7439		std::string l[4] = { "std140", "std430", "shared", "packed" };
7440		lo += l[layout];
7441		if (etype == matrix_rm)
7442			lo += ", row_major";
7443		std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7444						   ((other_members) ? ("\n  " + e[etype][0] + " pad0;") : "") + NL "  " + e[etype][0] +
7445						   " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7446						   ((other_members) ? ("\n  " + e[etype][1] + " pad1;") : "") + NL "  " + e[etype][1] +
7447						   " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7448						   ((other_members) ? ("\n  " + e[etype][2] + " pad2;") : "") + NL "  " + e[etype][2] +
7449						   " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7450						   ((other_members) ? ("\n  " + e[etype][4] + " pad4;") : "") + NL "  " + e[etype][4] +
7451						   " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7452						   ((other_members) ? ("\n  " + e[etype][5] + " pad5;") : "") + NL "  " + e[etype][5] +
7453						   " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7454						   ((other_members) ? ("\n  " + e[etype][6] + " pad6;") : "") + NL "  " + e[etype][6] +
7455						   " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7456						   "  int g_length[];" NL "};";
7457		std::string expr =
7458			NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7459			   "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7460			   "  g_length[4] = g_output0.data.length();" NL "  g_length[5] = g_input4.data.length();" NL
7461			   "  g_length[6] = g_output1.data.length();";
7462		std::string lastelemexpr =
7463			NL "  g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7464			   "  g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7465		if (length_as_index)
7466			expr += lastelemexpr;
7467		if (stage == vertex)
7468		{
7469			os << decl << NL "void main() {" NL "#ifdef GL_ES" NL "  gl_PointSize = 1.0f;" NL "#endif" NL
7470							 "  gl_Position = vec4(0,0,0,1);"
7471			   << expr;
7472		}
7473		if (stage == fragment)
7474		{
7475			os << NL "layout(location = 0) out vec4 o_color;" << decl
7476			   << NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" << expr;
7477		}
7478		if (stage == compute)
7479		{
7480			os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
7481		}
7482		os << NL "}";
7483		return os.str();
7484	}
7485
7486	virtual long Run()
7487	{
7488		const int kSize = 100000;
7489		const int kBufs = 8;
7490		SetPath();
7491		if ((stage == vertex && !IsVSFSAvailable(kBufs, 0)) || (stage == fragment && !IsVSFSAvailable(0, kBufs)))
7492			return NOT_SUPPORTED;
7493		GLint blocksC;
7494		glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
7495		GLint minA;
7496		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
7497		if (blocksC < kBufs)
7498			return NOT_SUPPORTED;
7499		if (stage == vertex)
7500		{
7501			std::string glsl_vs = BuildShader();
7502			std::string glsl_fs = BuildShaderPT(fragment);
7503			m_program			= CreateProgram(glsl_vs, glsl_fs);
7504		}
7505		else if (stage == fragment)
7506		{
7507			std::string glsl_vs = BuildShaderPT(vertex);
7508			std::string glsl_fs = BuildShader();
7509			m_program			= CreateProgram(glsl_vs, glsl_fs);
7510		}
7511		else
7512		{ // compute
7513			std::string glsl_cs = BuildShader();
7514			m_program			= CreateProgramCS(glsl_cs);
7515		}
7516		glLinkProgram(m_program);
7517		if (!CheckProgram(m_program))
7518			return ERROR;
7519		glUseProgram(m_program);
7520
7521		glGenBuffers(kBufs, m_storage_buffer);
7522		int sizes[kBufs]	  = { 7, 5, 3, 4, 23, 123, 419, 8 };
7523		int columns[4][kBufs] = { { 1, 1, 1, 1, 1, 1, 1, 1 },   // vector: 1 col
7524								  { 2, 3, 4, 4, 2, 3, 4, 1 },   // mat: # of cols
7525								  { 2, 3, 4, 4, 3, 2, 2, 1 },   // RM mat: # of rows
7526								  { 1, 1, 1, 1, 1, 1, 1, 1 } }; // structure: not used
7527		int scalars[4][kBufs] = { { 4, 4, 4, 4, 2, 2, 4, 1 },   //vector: size
7528								  { 2, 4, 4, 4, 4, 2, 2, 1 },   //matrix column_major: rows
7529								  { 2, 4, 4, 4, 2, 4, 4, 1 },   //matrix row_major: columns
7530								  { 1, 1, 1, 1, 1, 1, 1, 1 } }; //structure: not used
7531		int mindw[4][kBufs] = { { 3, 4, 3, 3, 2, 2, 4, 1 },		// # of real 32bit items
7532								{ 4, 9, 16, 16, 6, 6, 8, 1 },
7533								{ 4, 9, 16, 16, 6, 6, 8, 1 },
7534								{ 4, 11, 35, 35, 81, 127, 381, 1 } };
7535		int std430struct[kBufs] = { 4, 16, 48, 48, 88, 68, 264, 1 };
7536		int std140struct[kBufs] = { 4, 16, 60, 60, 144, 80, 432, 1 };
7537		int bufsize[kBufs][2]   = { { 0 }, { 0 } };
7538
7539		std::vector<ivec4> data(kSize, ivec4(41));
7540		for (int i = 0; i < kBufs; ++i)
7541		{
7542			if (layout == std430)
7543			{
7544				bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
7545				if (etype == structure)
7546				{
7547					bufsize[i][1] = 4 * std430struct[i];
7548				}
7549			}
7550			else if (layout == std140)
7551			{
7552				bufsize[i][1] = 4 * columns[etype][i] * 4;
7553				if (etype == structure)
7554				{
7555					bufsize[i][1] = 4 * std140struct[i];
7556				}
7557			}
7558			else
7559			{
7560				bufsize[i][1] = 4 * mindw[etype][i];
7561			}
7562			bufsize[i][0] = sizes[i] * bufsize[i][1];
7563			if (i == kBufs - 1 || bind_seq == bindbasebefore)
7564			{ // never trim feedback storage
7565				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7566				glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7567			}
7568			else
7569			{
7570				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
7571				glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
7572				if (bind_seq == bindbaseafter)
7573				{
7574					glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
7575				}
7576				else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
7577				{
7578					glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
7579									  bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7580				}
7581				else
7582				{ // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
7583					glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
7584									  bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
7585				}
7586			}
7587		}
7588
7589		if (stage != compute)
7590		{
7591			glGenVertexArrays(1, &m_vertex_array);
7592			glBindVertexArray(m_vertex_array);
7593			glDrawArrays(GL_POINTS, 0, 1);
7594		}
7595		else
7596		{
7597			glDispatchCompute(1, 1, 1);
7598		}
7599		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7600
7601		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
7602		int* dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
7603		if (!dataout)
7604			return ERROR;
7605		bool status = true;
7606		for (int i = 0; i < kBufs - 1; ++i)
7607		{
7608			if (other_members)
7609				sizes[i] -= 1; // space consumed by a pad
7610			if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
7611				sizes[i] -= 2; // space constrained by offset of range size
7612			if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
7613			{
7614				m_context.getTestContext().getLog()
7615					<< tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
7616					<< sizes[i] << tcu::TestLog::EndMessage;
7617				status = false;
7618			}
7619			if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
7620			{
7621				m_context.getTestContext().getLog()
7622					<< tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
7623					<< " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
7624				status = false;
7625			}
7626		}
7627		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7628
7629		if (length_as_index)
7630		{
7631			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7632			dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
7633			if (!dataout)
7634				return ERROR;
7635			int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
7636			if (dataout[i] != 82)
7637			{
7638				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
7639													<< dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7640				status = false;
7641			}
7642			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7643			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7644			dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
7645			if (!dataout)
7646				return ERROR;
7647			i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
7648			if (dataout[i] != 82)
7649			{
7650				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
7651													<< dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
7652				status = false;
7653			}
7654			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7655		}
7656
7657		if (!status)
7658			return ERROR;
7659
7660		return NO_ERROR;
7661	}
7662
7663public:
7664	int  stage;
7665	int  etype;
7666	int  layout;
7667	bool other_members;
7668	int  bind_seq;
7669	bool length_as_index;
7670
7671	AdvancedUnsizedArrayLength2()
7672		: m_program(0)
7673		, m_vertex_array(0)
7674		, stage(compute)
7675		, etype(vector)
7676		, layout(std430)
7677		, other_members(false)
7678		, bind_seq(bindbasebefore)
7679		, length_as_index(false)
7680	{
7681		for (int i = 0; i < 8; i++)
7682		{
7683			m_storage_buffer[i] = 0;
7684		}
7685	}
7686};
7687
7688class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7689{
7690public:
7691	virtual void SetPath()
7692	{
7693		length_as_index = true;
7694	}
7695};
7696
7697class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7698{
7699public:
7700	virtual void SetPath()
7701	{
7702		bind_seq = bindbaseafter;
7703	}
7704};
7705
7706class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7707{
7708public:
7709	virtual void SetPath()
7710	{
7711		bind_seq = bindrangeoffset;
7712	}
7713};
7714
7715class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7716{
7717public:
7718	virtual void SetPath()
7719	{
7720		bind_seq = bindrangesize;
7721	}
7722};
7723
7724class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7725{
7726public:
7727	virtual void SetPath()
7728	{
7729		etype = vector;
7730	}
7731};
7732
7733class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7734{
7735public:
7736	virtual void SetPath()
7737	{
7738		etype = matrix_cm;
7739	}
7740};
7741
7742class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7743{
7744public:
7745	virtual void SetPath()
7746	{
7747		etype = matrix_rm;
7748	}
7749};
7750
7751class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7752{
7753public:
7754	virtual void SetPath()
7755	{
7756		etype = structure;
7757	}
7758};
7759
7760class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7761{
7762public:
7763	virtual void SetPath()
7764	{
7765		stage  = compute;
7766		layout = std140;
7767	}
7768};
7769
7770class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7771{
7772public:
7773	virtual void SetPath()
7774	{
7775		etype  = matrix_cm;
7776		layout = std140;
7777	}
7778};
7779
7780class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7781{
7782public:
7783	virtual void SetPath()
7784	{
7785		etype  = matrix_rm;
7786		layout = std140;
7787	}
7788};
7789
7790class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7791{
7792public:
7793	virtual void SetPath()
7794	{
7795		etype  = structure;
7796		layout = std140;
7797	}
7798};
7799
7800class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7801{
7802public:
7803	virtual void SetPath()
7804	{
7805		etype  = vector;
7806		layout = packed;
7807	}
7808};
7809
7810class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7811{
7812public:
7813	virtual void SetPath()
7814	{
7815		etype  = matrix_cm;
7816		layout = packed;
7817	}
7818};
7819
7820class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7821{
7822public:
7823	virtual void SetPath()
7824	{
7825		etype  = matrix_rm;
7826		layout = shared;
7827	}
7828};
7829
7830class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7831{
7832public:
7833	virtual void SetPath()
7834	{
7835		stage  = fragment;
7836		etype  = vector;
7837		layout = std430;
7838	}
7839};
7840
7841class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7842{
7843public:
7844	virtual void SetPath()
7845	{
7846		stage		  = fragment;
7847		etype		  = matrix_cm;
7848		layout		  = std430;
7849		other_members = true;
7850	}
7851};
7852
7853class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7854{
7855public:
7856	virtual void SetPath()
7857	{
7858		stage  = fragment;
7859		etype  = matrix_rm;
7860		layout = std140;
7861	}
7862};
7863
7864class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7865{
7866public:
7867	virtual void SetPath()
7868	{
7869		stage  = fragment;
7870		etype  = structure;
7871		layout = std140;
7872	}
7873};
7874
7875class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7876{
7877public:
7878	virtual void SetPath()
7879	{
7880		stage		  = vertex;
7881		etype		  = vector;
7882		layout		  = std430;
7883		other_members = true;
7884	}
7885};
7886
7887class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7888{
7889public:
7890	virtual void SetPath()
7891	{
7892		stage  = vertex;
7893		etype  = matrix_cm;
7894		layout = std140;
7895	}
7896};
7897
7898class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7899{
7900public:
7901	virtual void SetPath()
7902	{
7903		stage  = vertex;
7904		etype  = matrix_rm;
7905		layout = packed;
7906	}
7907};
7908
7909class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7910{
7911public:
7912	virtual void SetPath()
7913	{
7914		stage  = vertex;
7915		etype  = structure;
7916		layout = std140;
7917	}
7918};
7919
7920class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7921{
7922public:
7923	virtual void SetPath()
7924	{
7925		etype		  = vector;
7926		other_members = true;
7927	}
7928};
7929
7930class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7931{
7932public:
7933	virtual void SetPath()
7934	{
7935		etype		  = matrix_cm;
7936		other_members = true;
7937	}
7938};
7939
7940class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7941{
7942public:
7943	virtual void SetPath()
7944	{
7945		etype		  = matrix_rm;
7946		layout		  = std140;
7947		other_members = true;
7948	}
7949};
7950
7951class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7952{
7953public:
7954	virtual void SetPath()
7955	{
7956		etype		  = structure;
7957		other_members = true;
7958	}
7959};
7960
7961//-----------------------------------------------------------------------------
7962// 2.8 AdvancedMatrix
7963//-----------------------------------------------------------------------------
7964class AdvancedMatrixVSFS : public ShaderStorageBufferObjectBase
7965{
7966	GLuint m_program;
7967	GLuint m_storage_buffer[3];
7968	GLuint m_vertex_array;
7969	GLuint m_vertex_buffer;
7970	GLuint m_fbo, m_rt;
7971
7972	virtual long Setup()
7973	{
7974		m_program = 0;
7975		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7976		m_vertex_array  = 0;
7977		m_vertex_buffer = 0;
7978		glGenFramebuffers(1, &m_fbo);
7979		glGenTextures(1, &m_rt);
7980		return NO_ERROR;
7981	}
7982
7983	virtual long Run()
7984	{
7985		if (!IsVSFSAvailable(2, 2))
7986			return NOT_SUPPORTED;
7987		const char* const glsl_vs =
7988			NL "layout(location = 0) in vec4 g_position;" NL "flat out int instance_id;" NL
7989			   "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
7990			   "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
7991			   "layout(binding = 1, std430) readonly buffer Buffer1 {" NL "  mat4 color;" NL "} g_buffer1;" NL
7992			   "uniform int g_index1;" NL "uniform int g_index2;" NL "void main() {" NL
7993			   "  gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
7994			   "  g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
7995			   "  if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL "    g_data0[1][1] = 1.0;" NL
7996			   "    g_data0[g_index1][g_index2] += 3.0;" NL "  }" NL "  memoryBarrier();" NL
7997			   "  instance_id = gl_InstanceID;" NL "}";
7998		const char* const glsl_fs =
7999			NL "flat in int instance_id;" NL "layout(location = 0) out vec4 g_ocolor;" NL
8000			   "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
8001			   "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8002			   "void main() {" NL "  if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
8003			   "  else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
8004			   "  else g_ocolor = vec4(g_color[instance_id], 1);" NL "}";
8005		m_program = CreateProgram(glsl_vs, glsl_fs);
8006		glLinkProgram(m_program);
8007		if (!CheckProgram(m_program))
8008			return ERROR;
8009
8010		glGenBuffers(3, m_storage_buffer);
8011
8012		/* transform buffer */
8013		{
8014			float data[48 + 16 + 12 + 16] = {
8015				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,
8016				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,
8017				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,
8018			};
8019			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8020			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8021		}
8022		/* transform buffer */
8023		{
8024			float data[16] = {
8025				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,
8026			};
8027			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8028			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8029		}
8030		/* vertex buffer */
8031		{
8032			float data[8] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
8033			glGenBuffers(1, &m_vertex_buffer);
8034			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8035			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8036			glBindBuffer(GL_ARRAY_BUFFER, 0);
8037		}
8038
8039		glBindTexture(GL_TEXTURE_2D, m_rt);
8040		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8041		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8042		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8043		glBindTexture(GL_TEXTURE_2D, 0);
8044		glViewport(0, 0, 100, 100);
8045		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8046		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_rt, 0);
8047
8048		glGenVertexArrays(1, &m_vertex_array);
8049		glBindVertexArray(m_vertex_array);
8050		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8051		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8052		glBindBuffer(GL_ARRAY_BUFFER, 0);
8053		glEnableVertexAttribArray(0);
8054		glBindVertexArray(0);
8055
8056		glClear(GL_COLOR_BUFFER_BIT);
8057		glUseProgram(m_program);
8058		glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8059		glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8060
8061		glBindVertexArray(m_vertex_array);
8062		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8063		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8064		{
8065			return ERROR;
8066		}
8067		return NO_ERROR;
8068	}
8069
8070	virtual long Cleanup()
8071	{
8072		glViewport(0, 0, getWindowWidth(), getWindowHeight());
8073		glUseProgram(0);
8074		glDeleteProgram(m_program);
8075		glDeleteBuffers(3, m_storage_buffer);
8076		glDeleteBuffers(1, &m_vertex_buffer);
8077		glDeleteVertexArrays(1, &m_vertex_array);
8078		glDeleteFramebuffers(1, &m_fbo);
8079		glDeleteTextures(1, &m_rt);
8080		return NO_ERROR;
8081	}
8082};
8083
8084class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8085{
8086	GLuint m_program;
8087	GLuint m_storage_buffer;
8088
8089	virtual long Setup()
8090	{
8091		m_program		 = 0;
8092		m_storage_buffer = 0;
8093		return NO_ERROR;
8094	}
8095
8096	virtual long Run()
8097	{
8098		bool			  status = true;
8099		const char* const glsl_cs =
8100			NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL "  mat4x3 dst4x3;" NL
8101			   "  mat4 dst4;" NL "  mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8102			   "void main() {" NL "  b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8103			   "  b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8104			   "  b.dst4[g_index2][g_index1] = 17.0;" NL "  b.dst4[g_index2][g_index1] += 6.0;" NL
8105			   "  b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL "  b.dst4[3][1] = b.src4[3][1];" NL "}";
8106		m_program = CreateProgramCS(glsl_cs);
8107		glLinkProgram(m_program);
8108		if (!CheckProgram(m_program))
8109			return ERROR;
8110
8111		glGenBuffers(1, &m_storage_buffer);
8112		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8113		GLfloat data[16 + 16 + 16];
8114		for (int i  = 0; i < 32; ++i)
8115			data[i] = 0.0f;
8116		for (int i  = 32; i < 48; ++i)
8117			data[i] = (GLfloat)i;
8118		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8119
8120		glUseProgram(m_program);
8121		glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8122		glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8123		glDispatchCompute(1, 1, 1);
8124		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8125		GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8126		if (!out_data)
8127			return ERROR;
8128		GLfloat expected[32] = { 32.0f, 33.0f, 34.0f, 0.0f, 39.0f, 39.0f, 36.0f, 0.0f,
8129								 0.0f,  0.0f,  0.0f,  0.0f, 0.0f,  0.0f,  0.0f,  0.0f,
8130
8131								 0.0f,  0.0f,  0.0f,  0.0f, 0.0f,  0.0f,  0.0f,  0.0f,
8132								 0.0f,  23.0f, 0.0f,  0.0f, 7.0f,  45.0f, 0.0f,  0.0f };
8133		for (int i = 0; i < 32; ++i)
8134		{
8135			if (out_data[i] != expected[i])
8136			{
8137				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8138													<< ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8139				status = false;
8140			}
8141		}
8142		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8143		if (status)
8144			return NO_ERROR;
8145		else
8146			return ERROR;
8147	}
8148
8149	virtual long Cleanup()
8150	{
8151		glUseProgram(0);
8152		glDeleteProgram(m_program);
8153		glDeleteBuffers(1, &m_storage_buffer);
8154		return NO_ERROR;
8155	}
8156};
8157
8158//-----------------------------------------------------------------------------
8159// 4.1.1 NegativeAPIBind
8160//-----------------------------------------------------------------------------
8161class NegativeAPIBind : public ShaderStorageBufferObjectBase
8162{
8163	virtual long Run()
8164	{
8165		GLint  bindings;
8166		GLint  alignment;
8167		GLuint buffer;
8168		glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8169		m_context.getTestContext().getLog()
8170			<< tcu::TestLog::Message << "Max storage buffer bindings " << bindings << tcu::TestLog::EndMessage;
8171		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8172		m_context.getTestContext().getLog()
8173			<< tcu::TestLog::Message << "Storage buffer offset alignment " << alignment << tcu::TestLog::EndMessage;
8174
8175		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8176		if (glGetError() != GL_INVALID_VALUE)
8177		{
8178			m_context.getTestContext().getLog()
8179				<< tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8180				<< "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8181				<< "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8182			return ERROR;
8183		}
8184
8185		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8186		if (glGetError() != GL_INVALID_VALUE)
8187		{
8188			m_context.getTestContext().getLog()
8189				<< tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8190				<< "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8191				<< "MAX_SHADER_STORAGE_BUFFER_BINDINGS." << tcu::TestLog::EndMessage;
8192			return ERROR;
8193		}
8194
8195		glGenBuffers(1, &buffer);
8196		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, buffer, alignment - 1, 0);
8197		if (glGetError() != GL_INVALID_VALUE)
8198		{
8199			m_context.getTestContext().getLog()
8200				<< tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8201				<< "SHADER_STORAGE_BUFFER and <offset>  is not a multiple of the value of\n"
8202				<< "SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT." << tcu::TestLog::EndMessage;
8203			return ERROR;
8204		}
8205
8206		return NO_ERROR;
8207	}
8208};
8209
8210//-----------------------------------------------------------------------------
8211// 4.2.1 NegativeGLSLCompileTime
8212//-----------------------------------------------------------------------------
8213class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8214{
8215	static std::string Shader1(int binding)
8216	{
8217		std::stringstream ss;
8218		ss << NL "layout(binding = " << binding
8219		   << ") buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8220		return ss.str();
8221	}
8222
8223	static std::string Shader2(int binding)
8224	{
8225		std::stringstream ss;
8226		ss << NL "layout(binding = " << binding
8227		   << ") buffer Buffer {" NL "  int x;" NL "} g_array[4];" NL "void main() {" NL "  g_array[0].x = 0;" NL
8228			  "  g_array[1].x = 0;" NL "  g_array[2].x = 0;" NL "  g_array[3].x = 0;" NL "}";
8229		return ss.str();
8230	}
8231
8232	virtual long Run()
8233	{
8234		GLint bindings;
8235		glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8236
8237		//  initialization of buffer block member 'x' not allowed
8238		if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL "  x = 0;" NL "}"))
8239			return ERROR;
8240
8241		//  syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8242		if (!Compile(Shader1(-1)))
8243			return ERROR;
8244		//  invalid value 96 for layout specifier 'binding'
8245		if (!Compile(Shader1(bindings)))
8246			return ERROR;
8247
8248		//  invalid value 98 for layout specifier 'binding'
8249		if (!Compile(Shader2(bindings - 2)))
8250			return ERROR;
8251
8252		//  OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8253		if (!Compile(NL "buffer int x;" NL "void main() {" NL "  x = 0;" NL "}"))
8254			return ERROR;
8255
8256		// OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8257		if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL "  y = 0;" NL "  buffer int x = 0;" NL "}"))
8258			return ERROR;
8259
8260		//  OpenGL does not allow a parameter to be a buffer
8261		if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL "  atomicAdd(a, 1);" NL "}" NL
8262						"void main() {" NL "  Modify(y);" NL "}"))
8263			return ERROR;
8264
8265		//  layout specifier 'std430', incompatible with 'uniform blocks'
8266		if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8267						"  y = x;" NL "}"))
8268			return ERROR;
8269
8270		//  unknown layout specifier 'std430'
8271		if (!Compile(NL "buffer SSBO {" NL "  layout(std430) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8272			return ERROR;
8273
8274		//  unknown layout specifier 'binding = 1'
8275		if (!Compile(NL "buffer SSBO {" NL "  layout(binding = 1) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL
8276						"}"))
8277			return ERROR;
8278
8279		//  OpenGL does not allow writing to readonly variable 'x'
8280		if (!Compile(NL "readonly buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8281			return ERROR;
8282
8283		//  OpenGL does not allow reading writeonly variable 'y'
8284		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "writeonly buffer SSBO2 {" NL "  int y;" NL "};" NL
8285						"void main() {" NL "  x = y;" NL "}"))
8286			return ERROR;
8287
8288		//  OpenGL does not allow writing to readonly variable 'z'
8289		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "buffer SSBO2 {" NL "  writeonly int y;" NL
8290						"  readonly int z;" NL "};" NL "void main() {" NL "  x = y;" NL "  z = 0;" NL "}"))
8291			return ERROR;
8292
8293		//  OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8294		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "readonly buffer SSBO2 {" NL "  writeonly int y;" NL
8295						"};" NL "void main() {" NL "  x = y;" NL "}"))
8296			return ERROR;
8297
8298		// ["layout(binding = 1) buffer;" should cause compile-time error
8299		if (!Compile(NL "layout(binding = 1) buffer;" //
8300					 NL "buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8301			return ERROR;
8302
8303		// ["  atomicAdd(y, 2);"  should cause compile-time error
8304		if (!Compile(NL "buffer coherent Buffer { int x; };" NL "int y;" NL "void main() {" NL "  atomicAdd(x, 1);" NL
8305						"  atomicAdd(y, 2);" //
8306					 NL "}"))
8307			return ERROR;
8308
8309		if (!Compile( // can't construct vector from an array
8310				NL "buffer b {" NL "  vec4 x[10];" NL "};" NL "void main() {" NL "  vec4 y = vec4(x);" NL "}"))
8311			return ERROR;
8312
8313		if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8314				NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
8315				   "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
8316				   "void main() {" NL "  for (int i = 0; i < 4; ++i) {" NL
8317				   "    g_output[i].data0 = g_input[i].data0;" NL "  }" NL "}"))
8318			return ERROR;
8319
8320		if (!Compile( // ESSL31 does not allow dynamically uniform indexing of SSBO arrays
8321				NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL "} g_material[4];" NL
8322				   "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL "};" NL
8323				   "uniform int g_material_id;" NL "void main() {" NL
8324				   "  color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}"))
8325			return ERROR;
8326
8327		return NO_ERROR;
8328	}
8329	bool Compile(const std::string& source)
8330	{
8331		const char* const csVer  = "#version 310 es" NL "layout(local_size_x = 1) in;";
8332		const char* const src[2] = { csVer, source.c_str() };
8333		const GLuint	  sh	 = glCreateShader(GL_COMPUTE_SHADER);
8334		glShaderSource(sh, 2, src, NULL);
8335		glCompileShader(sh);
8336
8337		GLchar log[1024];
8338		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8339		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8340											<< log << tcu::TestLog::EndMessage;
8341
8342		GLint status;
8343		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8344		glDeleteShader(sh);
8345
8346		if (status == GL_TRUE)
8347		{
8348			m_context.getTestContext().getLog()
8349				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8350			return false;
8351		}
8352
8353		return true;
8354	}
8355};
8356
8357//-----------------------------------------------------------------------------
8358// 4.2.2 NegativeGLSLLinkTime
8359//-----------------------------------------------------------------------------
8360class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8361{
8362	virtual long Run()
8363	{
8364		if (!IsVSFSAvailable(1, 1))
8365			return NOT_SUPPORTED;
8366		if (!Link("#version 310 es" NL "buffer Buffer { int x; };" NL "void main() {" NL "  x += 2;" NL "}",
8367				  "#version 310 es" NL "precision highp float;" NL "buffer Buffer { uint x; };" NL "void main() {" NL
8368				  "  x += 3u;" NL "}"))
8369			return ERROR;
8370
8371		if (!Link("#version 310 es" NL "buffer Buffer { int x; int y; };" NL "void main() {" NL "  x += 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 y; };" NL "void main() {" NL "  y += 2;" NL "}",
8377				  "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x; };" NL "void main() {" NL
8378				  "  x += 3;" NL "}"))
8379			return ERROR;
8380
8381		if (!Link("#version 310 es" NL "buffer Buffer { int x[2]; };" NL "void main() {" NL "  x[1] += 2;" NL "}",
8382				  "#version 310 es" NL "precision highp float;" NL "buffer Buffer { int x[3]; };" NL "void main() {" NL
8383				  "  x[1] += 3;" NL "}"))
8384			return ERROR;
8385
8386		return NO_ERROR;
8387	}
8388	bool Link(const std::string& cs0, const std::string& cs1)
8389	{
8390		const GLuint p = glCreateProgram();
8391
8392		/* shader 0 */
8393		{
8394			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8395			glAttachShader(p, sh);
8396			glDeleteShader(sh);
8397			const char* const src = cs0.c_str();
8398			glShaderSource(sh, 1, &src, NULL);
8399			glCompileShader(sh);
8400
8401			GLint status;
8402			glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8403			if (status == GL_FALSE)
8404			{
8405				m_context.getTestContext().getLog()
8406					<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
8407				CheckProgram(p);
8408				glDeleteProgram(p);
8409				return false;
8410			}
8411		}
8412		/* shader 1 */
8413		{
8414			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8415			glAttachShader(p, sh);
8416			glDeleteShader(sh);
8417			const char* const src = cs1.c_str();
8418			glShaderSource(sh, 1, &src, NULL);
8419			glCompileShader(sh);
8420
8421			GLint status;
8422			glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8423			if (status == GL_FALSE)
8424			{
8425				m_context.getTestContext().getLog()
8426					<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
8427				CheckProgram(p);
8428				glDeleteProgram(p);
8429				return false;
8430			}
8431		}
8432
8433		glLinkProgram(p);
8434
8435		GLchar log[1024];
8436		glGetProgramInfoLog(p, sizeof(log), NULL, log);
8437		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
8438											<< log << tcu::TestLog::EndMessage;
8439
8440		GLint status;
8441		glGetProgramiv(p, GL_LINK_STATUS, &status);
8442		glDeleteProgram(p);
8443
8444		if (status == GL_TRUE)
8445		{
8446			m_context.getTestContext().getLog()
8447				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
8448			return false;
8449		}
8450
8451		return true;
8452	}
8453};
8454} // anonymous namespace
8455
8456ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
8457	: TestCaseGroup(context, "shader_storage_buffer_object", "")
8458{
8459}
8460
8461ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8462{
8463}
8464
8465void ShaderStorageBufferObjectTests::init()
8466{
8467	using namespace deqp;
8468	addChild(new TestSubcase(m_context, "basic-basic-vs", TestSubcase::Create<BasicBasicVS>));
8469	addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
8470	addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
8471	addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
8472	addChild(new TestSubcase(m_context, "basic-syntax-vs", TestSubcase::Create<BasicSyntaxVS>));
8473	addChild(new TestSubcase(m_context, "basic-syntax-cs", TestSubcase::Create<BasicSyntaxCS>));
8474	addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
8475	addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
8476	addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
8477	addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
8478	addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
8479	addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
8480	addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
8481	addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
8482	addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
8483	addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
8484	addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
8485	addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
8486	addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
8487	addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
8488	addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
8489	addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
8490	addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
8491	addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
8492	addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
8493	addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
8494	addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
8495	addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
8496	addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
8497	addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
8498	addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
8499	addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
8500	addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
8501	addChild(new TestSubcase(m_context, "basic-atomic-case1-vsfs", TestSubcase::Create<BasicAtomicCase1VSFS>));
8502	addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
8503	addChild(new TestSubcase(m_context, "basic-atomic-case3-vsfs", TestSubcase::Create<BasicAtomicCase3VSFS>));
8504	addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
8505	addChild(new TestSubcase(m_context, "basic-atomic-case4-vsfs", TestSubcase::Create<BasicAtomicCase4VSFS>));
8506	addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
8507	addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
8508	addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
8509	addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
8510	addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
8511	addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
8512	addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
8513	addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
8514	addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
8515	addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
8516	addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
8517	addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
8518	addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
8519	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
8520							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
8521	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
8522							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
8523	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
8524							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
8525	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
8526							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
8527	addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
8528							 TestSubcase::Create<BasicMatrixOperationsCase1VS>));
8529	addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
8530							 TestSubcase::Create<BasicMatrixOperationsCase1CS>));
8531	addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
8532							 TestSubcase::Create<BasicMatrixOperationsCase2VS>));
8533	addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
8534							 TestSubcase::Create<BasicMatrixOperationsCase2CS>));
8535	addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
8536							 TestSubcase::Create<BasicMatrixOperationsCase3VS>));
8537	addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
8538							 TestSubcase::Create<BasicMatrixOperationsCase3CS>));
8539	addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
8540							 TestSubcase::Create<BasicMatrixOperationsCase4VS>));
8541	addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
8542							 TestSubcase::Create<BasicMatrixOperationsCase4CS>));
8543	addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
8544							 TestSubcase::Create<BasicMatrixOperationsCase5VS>));
8545	addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
8546							 TestSubcase::Create<BasicMatrixOperationsCase5CS>));
8547	addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
8548							 TestSubcase::Create<BasicMatrixOperationsCase6VS>));
8549	addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
8550							 TestSubcase::Create<BasicMatrixOperationsCase6CS>));
8551	addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
8552							 TestSubcase::Create<BasicMatrixOperationsCase7VS>));
8553	addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
8554							 TestSubcase::Create<BasicMatrixOperationsCase7CS>));
8555	addChild(new TestSubcase(m_context, "advanced-switchBuffers-vs", TestSubcase::Create<AdvancedSwitchBuffersVS>));
8556	addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
8557	addChild(new TestSubcase(m_context, "advanced-switchPrograms-vs", TestSubcase::Create<AdvancedSwitchProgramsVS>));
8558	addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
8559	addChild(new TestSubcase(m_context, "advanced-write-fragment-fs", TestSubcase::Create<AdvancedWriteFragmentFS>));
8560	addChild(new TestSubcase(m_context, "advanced-write-fragment-cs", TestSubcase::Create<AdvancedWriteFragmentCS>));
8561	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-vs",
8562							 TestSubcase::Create<AdvancedIndirectAddressingCase1VS>));
8563	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
8564							 TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
8565	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-vsfs",
8566							 TestSubcase::Create<AdvancedIndirectAddressingCase2VSFS>));
8567	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
8568							 TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
8569	addChild(
8570		new TestSubcase(m_context, "advanced-readWrite-case1-vsfs", TestSubcase::Create<AdvancedReadWriteCase1VSFS>));
8571	addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
8572	addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
8573	addChild(new TestSubcase(m_context, "advanced-usage-sync-vsfs", TestSubcase::Create<AdvancedUsageSyncVSFS>));
8574	addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
8575	addChild(new TestSubcase(m_context, "advanced-usage-operators-vs", TestSubcase::Create<AdvancedUsageOperatorsVS>));
8576	addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
8577	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-int",
8578							 TestSubcase::Create<AdvancedUnsizedArrayLength<compute> >));
8579	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-int",
8580							 TestSubcase::Create<AdvancedUnsizedArrayLength<fragment> >));
8581	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-int",
8582							 TestSubcase::Create<AdvancedUnsizedArrayLength<vertex> >));
8583	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
8584							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
8585	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
8586							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
8587	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
8588							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
8589	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
8590							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
8591	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
8592							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
8593	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
8594							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
8595	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
8596							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
8597	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
8598							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
8599	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
8600							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
8601	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
8602							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
8603	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
8604							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
8605	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
8606							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
8607	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
8608							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
8609	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
8610							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
8611	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
8612							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
8613	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
8614							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
8615	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
8616							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
8617	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
8618							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
8619	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
8620							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
8621	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
8622							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
8623	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
8624							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
8625	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
8626							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
8627	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
8628							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
8629
8630	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
8631							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
8632
8633	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
8634							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
8635
8636	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
8637							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
8638
8639	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
8640							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
8641
8642	addChild(new TestSubcase(m_context, "advanced-matrix-vsfs", TestSubcase::Create<AdvancedMatrixVSFS>));
8643	addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
8644	addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
8645	addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
8646	addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
8647}
8648
8649} // namespace es31compatibility
8650} // namespace gl4cts
8651