• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cES31CompatibilityTests.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuMatrix.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include <assert.h>
29 #include <cmath>
30 #include <cstdarg>
31 
32 namespace gl4cts
33 {
34 
35 namespace es31compatibility
36 {
37 using namespace glw;
38 
39 namespace
40 {
41 
42 typedef tcu::Vec2  vec2;
43 typedef tcu::Vec3  vec3;
44 typedef tcu::Vec4  vec4;
45 typedef tcu::IVec4 ivec4;
46 typedef tcu::UVec4 uvec4;
47 typedef tcu::Mat4  mat4;
48 
49 enum ShaderStage
50 {
51 	vertex,
52 	fragment,
53 	compute
54 };
55 enum BufferLayout
56 {
57 	std140,
58 	std430,
59 	shared,
60 	packed
61 };
62 enum ElementType
63 {
64 	vector,
65 	matrix_cm,
66 	matrix_rm,
67 	structure
68 };
69 enum BindingSeq
70 {
71 	bindbasebefore,
72 	bindbaseafter,
73 	bindrangeoffset,
74 	bindrangesize
75 };
76 
77 const char* const kGLSLVer = "#version 310 es" NL "precision highp float;" NL "precision highp int;";
78 
79 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
80 {
Title()81 	virtual std::string Title()
82 	{
83 		return "";
84 	}
85 
Purpose()86 	virtual std::string Purpose()
87 	{
88 		return "";
89 	}
90 
Method()91 	virtual std::string Method()
92 	{
93 		return "";
94 	}
95 
PassCriteria()96 	virtual std::string PassCriteria()
97 	{
98 		return "";
99 	}
100 
101 public:
IsVSFSAvailable(int requiredVS,int requiredFS)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 
getWindowWidth()121 	int getWindowWidth()
122 	{
123 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
124 		return renderTarget.getWidth();
125 	}
126 
getWindowHeight()127 	int getWindowHeight()
128 	{
129 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
130 		return renderTarget.getHeight();
131 	}
132 
CheckProgram(GLuint program)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 
CreateProgram(const std::string & vs,const std::string & fs)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 	}
CreateProgramCS(const std::string & cs)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 
BuildShaderProgram(GLenum type,const std::string & source)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 
ColorEqual(int x,int y,const vec3 & c0,const vec3 & expected,const vec3 & epsilon,const vec3 & color_max)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 
CheckFB(vec3 expected)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 
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)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 
Translation(float tx,float ty,float tz)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 
GLenumToString(GLenum e)448 	const char* GLenumToString(GLenum e)
449 	{
450 		switch (e)
451 		{
452 		case GL_SHADER_STORAGE_BUFFER_BINDING:
453 			return "GL_SHADER_STORAGE_BUFFER_BINDING";
454 		case GL_SHADER_STORAGE_BUFFER_START:
455 			return "GL_SHADER_STORAGE_BUFFER_START";
456 		case GL_SHADER_STORAGE_BUFFER_SIZE:
457 			return "GL_SHADER_STORAGE_BUFFER_SIZE";
458 		case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
459 			return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
460 		case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
461 			return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
462 		case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
463 			return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
464 		case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
465 			return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
466 		case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
467 			return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
468 		case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
469 			return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
470 		case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
471 			return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
472 		case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
473 			return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
474 
475 		default:
476 			assert(0);
477 			break;
478 		}
479 		return NULL;
480 	}
481 };
482 
483 //-----------------------------------------------------------------------------
484 // 1.1 BasicBasic
485 //-----------------------------------------------------------------------------
486 class BasicBasicVS : public ShaderStorageBufferObjectBase
487 {
488 	GLuint m_program;
489 	GLuint m_buffer;
490 	GLuint m_vertex_array;
491 
Setup()492 	virtual long Setup()
493 	{
494 		m_program	  = 0;
495 		m_buffer	   = 0;
496 		m_vertex_array = 0;
497 		return NO_ERROR;
498 	}
499 
Run()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 
Cleanup()536 	virtual long Cleanup()
537 	{
538 		glUseProgram(0);
539 		glDeleteProgram(m_program);
540 		glDeleteBuffers(1, &m_buffer);
541 		glDeleteVertexArrays(1, &m_vertex_array);
542 		return NO_ERROR;
543 	}
544 };
545 
546 class BasicBasicCS : public ShaderStorageBufferObjectBase
547 {
548 	GLuint m_program;
549 	GLuint m_buffer;
550 
Setup()551 	virtual long Setup()
552 	{
553 		m_program = 0;
554 		m_buffer  = 0;
555 		return NO_ERROR;
556 	}
557 
Run()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 
Cleanup()585 	virtual long Cleanup()
586 	{
587 		glUseProgram(0);
588 		glDeleteProgram(m_program);
589 		glDeleteBuffers(1, &m_buffer);
590 		return NO_ERROR;
591 	}
592 };
593 
594 //-----------------------------------------------------------------------------
595 // 1.2 BasicMax
596 //-----------------------------------------------------------------------------
597 class BasicMax : public ShaderStorageBufferObjectBase
598 {
Check(GLenum e,GLint64 value,bool max_value)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 
Run()647 	virtual long Run()
648 	{
649 		if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
650 			return ERROR;
651 		if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 0, true))
652 			return ERROR;
653 		if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 4, true))
654 			return ERROR;
655 		if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 4, true))
656 			return ERROR;
657 		if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 134217728 /* 2^27 */, true))
658 			return ERROR;
659 		if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 4, true))
660 			return ERROR;
661 		if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4, true))
662 			return ERROR;
663 		if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
664 			return ERROR;
665 		return NO_ERROR;
666 	}
667 };
668 //-----------------------------------------------------------------------------
669 // 1.3 BasicBinding
670 //-----------------------------------------------------------------------------
671 class BasicBinding : public ShaderStorageBufferObjectBase
672 {
673 	GLuint m_buffer[4];
674 
Check(GLenum e,GLuint expected)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 
CheckIndexed(GLenum e,GLuint index,GLuint expected)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 
Setup()729 	virtual long Setup()
730 	{
731 		memset(m_buffer, 0, sizeof(m_buffer));
732 		return NO_ERROR;
733 	}
734 
Run()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 
Cleanup()859 	virtual long Cleanup()
860 	{
861 		glDeleteBuffers(4, m_buffer);
862 		return NO_ERROR;
863 	}
864 };
865 
866 //-----------------------------------------------------------------------------
867 // 1.4 BasicSyntax
868 //-----------------------------------------------------------------------------
869 class BasicSyntaxVS : public ShaderStorageBufferObjectBase
870 {
871 	GLuint m_program;
872 	GLuint m_buffer;
873 	GLuint m_vertex_array;
874 
RunIteration(const char * vs,const char * fs)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 
Setup()891 	virtual long Setup()
892 	{
893 		m_program	  = 0;
894 		m_buffer	   = 0;
895 		m_vertex_array = 0;
896 		return NO_ERROR;
897 	}
898 
Run()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 
Cleanup()955 	virtual long Cleanup()
956 	{
957 		glUseProgram(0);
958 		glDeleteProgram(m_program);
959 		glDeleteBuffers(1, &m_buffer);
960 		glDeleteVertexArrays(1, &m_vertex_array);
961 		return NO_ERROR;
962 	}
963 };
964 
965 class BasicSyntaxCS : public ShaderStorageBufferObjectBase
966 {
967 	GLuint m_program;
968 	GLuint m_buffer[2];
969 
RunIteration(const char * cs)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 
Setup()998 	virtual long Setup()
999 	{
1000 		m_program = 0;
1001 		memset(m_buffer, 0, sizeof(m_buffer));
1002 		return NO_ERROR;
1003 	}
1004 
Run()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 
Cleanup()1074 	virtual long Cleanup()
1075 	{
1076 		glUseProgram(0);
1077 		glDeleteProgram(m_program);
1078 		glDeleteBuffers(2, m_buffer);
1079 		return NO_ERROR;
1080 	}
1081 };
1082 //-----------------------------------------------------------------------------
1083 // 1.5 BasicSyntaxSSO
1084 //-----------------------------------------------------------------------------
1085 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1086 {
1087 	GLuint m_pipeline;
1088 	GLuint m_vsp, m_fsp;
1089 	GLuint m_buffer;
1090 	GLuint m_vertex_array;
1091 
RunIteration(const char * vs)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 
Setup()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 
Run()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 
Cleanup()1181 	virtual long Cleanup()
1182 	{
1183 		glDeleteProgramPipelines(1, &m_pipeline);
1184 		glDeleteProgram(m_vsp);
1185 		glDeleteProgram(m_fsp);
1186 		glDeleteBuffers(1, &m_buffer);
1187 		glDeleteVertexArrays(1, &m_vertex_array);
1188 		return NO_ERROR;
1189 	}
1190 };
1191 
1192 //-----------------------------------------------------------------------------
1193 // 1.6.x BasicStdLayoutBase
1194 //-----------------------------------------------------------------------------
1195 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1196 {
1197 	GLuint m_program;
1198 	GLuint m_buffer[2];
1199 	GLuint m_vertex_array;
1200 
1201 	virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1202 
Setup()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 
Run()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 
Cleanup()1265 	virtual long Cleanup()
1266 	{
1267 		glDisable(GL_RASTERIZER_DISCARD);
1268 		glUseProgram(0);
1269 		glDeleteProgram(m_program);
1270 		glDeleteBuffers(2, m_buffer);
1271 		glDeleteVertexArrays(1, &m_vertex_array);
1272 		return NO_ERROR;
1273 	}
1274 };
1275 
1276 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1277 {
1278 	GLuint m_program;
1279 	GLuint m_buffer[2];
1280 
1281 	virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1282 
Setup()1283 	virtual long Setup()
1284 	{
1285 		m_program = 0;
1286 		memset(m_buffer, 0, sizeof(m_buffer));
1287 		return NO_ERROR;
1288 	}
1289 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1351 const char* GetInput430c1(std::vector<GLubyte>& in_data)
1352 {
1353 	in_data.resize(6 * 4);
1354 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1355 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1356 	fp[0]	 = 1.0f;
1357 	fp[1]	 = 2.0f;
1358 	fp[2]	 = 3.0f;
1359 	fp[3]	 = 4.0f;
1360 	ip[4]	 = 5;
1361 	ip[5]	 = 6;
1362 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1363 			  "  ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL
1364 			  "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1365 			  "  g_output.data0 = g_input.data0;" NL
1366 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1367 			  "  g_output.data2 = g_input.data2;" NL "}";
1368 }
1369 
1370 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1371 {
GetInput(std::vector<GLubyte> & in_data)1372 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1373 	{
1374 		return GetInput430c1(in_data);
1375 	}
1376 };
1377 
1378 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1379 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1389 const char* GetInput430c2(std::vector<GLubyte>& in_data)
1390 {
1391 	in_data.resize(17 * 4);
1392 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1393 	fp[0]	 = 1.0f;
1394 	fp[1]	 = 2.0f;
1395 	fp[2]	 = 3.0f;
1396 	fp[3]	 = 4.0f;
1397 	fp[4]	 = 5.0f;
1398 	fp[5]	 = 6.0f;
1399 	fp[8]	 = 7.0f;
1400 	fp[9]	 = 8.0f;
1401 	fp[10]	= 9.0f;
1402 	fp[12]	= 10.0f;
1403 	fp[13]	= 11.0f;
1404 	fp[14]	= 12.0f;
1405 	fp[16]	= 13.0f;
1406 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1407 			  "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1408 			  "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1409 			  "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1410 			  "  g_output.data0 = g_input.data0;" NL
1411 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1412 			  "  g_output.data2 = g_input.data2;" NL
1413 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1414 			  "  g_output.data4 = g_input.data4;" NL "}";
1415 }
1416 
1417 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1418 {
GetInput(std::vector<GLubyte> & in_data)1419 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1420 	{
1421 		return GetInput430c2(in_data);
1422 	}
1423 };
1424 
1425 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1426 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1436 const char* GetInput430c3(std::vector<GLubyte>& in_data)
1437 {
1438 	in_data.resize(16 * 4);
1439 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1440 	fp[0]	 = 1.0f;
1441 	fp[1]	 = 2.0f;
1442 	fp[2]	 = 3.0f;
1443 	fp[3]	 = 0.0f;
1444 	fp[4]	 = 4.0f;
1445 	fp[5]	 = 5.0f;
1446 	fp[6]	 = 6.0f;
1447 	fp[7]	 = 0.0f;
1448 	fp[8]	 = 7.0f;
1449 	fp[9]	 = 8.0f;
1450 	fp[10]	= 9.0f;
1451 	fp[11]	= 10.0f;
1452 	fp[12]	= 11.0f;
1453 	fp[13]	= 12.0f;
1454 	fp[14]	= 13.0f;
1455 	fp[15]	= 14.0f;
1456 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat2x3 data0;" NL
1457 			  "  layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1458 			  "  layout(column_major) mat2x3 data0;" NL "  layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1459 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL "}";
1460 }
1461 
1462 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1463 {
GetInput(std::vector<GLubyte> & in_data)1464 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1465 	{
1466 		return GetInput430c3(in_data);
1467 	}
1468 };
1469 
1470 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1471 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1481 const char* GetInput430c4(std::vector<GLubyte>& in_data)
1482 {
1483 	in_data.resize(17 * 4);
1484 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1485 	fp[0]	 = 1.0f;
1486 	fp[1]	 = 2.0f;
1487 	fp[2]	 = 3.0f;
1488 	fp[3]	 = 4.0f;
1489 	fp[4]	 = 5.0f;
1490 	fp[5]	 = 6.0f;
1491 	fp[6]	 = 7.0f;
1492 	fp[7]	 = 8.0f;
1493 	fp[8]	 = 9.0f;
1494 	fp[9]	 = 10.0f;
1495 	fp[10]	= 11.0f;
1496 	fp[12]	= 12.0f;
1497 	fp[13]	= 13.0f;
1498 	fp[14]	= 14.0f;
1499 	fp[16]	= 15.0f;
1500 
1501 	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1502 			  "  float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1503 			  "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1504 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1505 			  "  g_output.data2 = g_input.data2;" NL "}";
1506 }
1507 
1508 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1509 {
GetInput(std::vector<GLubyte> & in_data)1510 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1511 	{
1512 		return GetInput430c4(in_data);
1513 	}
1514 };
1515 
1516 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1517 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1526 const char* GetInput430c5(std::vector<GLubyte>& in_data)
1527 {
1528 	in_data.resize(8 * 4);
1529 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1530 	fp[0]	 = 1.0f;
1531 	fp[1]	 = 3.0f;
1532 	fp[2]	 = 5.0f;
1533 	fp[3]	 = 7.0f;
1534 	fp[4]	 = 2.0f;
1535 	fp[5]	 = 4.0f;
1536 	fp[6]	 = 6.0f;
1537 	fp[7]	 = 8.0f;
1538 
1539 	return NL "layout(std430, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1540 			  "layout(std430, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1541 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1542 }
1543 
1544 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1545 {
GetInput(std::vector<GLubyte> & in_data)1546 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1547 	{
1548 		return GetInput430c5(in_data);
1549 	}
1550 };
1551 
1552 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1553 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1563 const char* GetInput430c6(std::vector<GLubyte>& in_data)
1564 {
1565 	in_data.resize(92 * 4);
1566 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1567 	fp[0]	 = 1.0f;
1568 	fp[1]	 = 2.0f;
1569 	fp[2]	 = 3.0f;
1570 	fp[3]	 = 4.0f;
1571 	fp[4]	 = 5.0f;
1572 	fp[5]	 = 0.0f;
1573 	fp[6]	 = 6.0f;
1574 	fp[7]	 = 7.0f;
1575 	fp[8]	 = 8.0f;
1576 	fp[9]	 = 9.0f;
1577 	fp[10]	= 10.0f;
1578 	fp[11]	= 11.0f;
1579 	fp[12]	= 12.0f;
1580 	fp[13]	= 0.0f;
1581 	fp[14]	= 0.0f;
1582 	fp[15]	= 0.0f;
1583 	fp[16]	= 13.0f;
1584 	fp[17]	= 14.0f;
1585 	fp[18]	= 15.0f;
1586 	fp[19]	= 0.0f;
1587 	fp[20]	= 16.0f;
1588 	fp[21]	= 17.0f;
1589 	fp[22]	= 18.0f;
1590 	fp[23]	= 0.0f;
1591 	fp[24]	= 19.0f;
1592 	fp[25]	= 20.0f;
1593 	fp[26]	= 21.0f;
1594 	fp[27]	= 22.0f;
1595 	fp[28]	= 23.0f;
1596 	fp[29]	= 24.0f;
1597 	fp[30]	= 25.0f;
1598 	fp[31]	= 26.0f;
1599 	fp[32]	= 27.0f;
1600 	fp[33]	= 28.0f;
1601 	fp[34]	= 0.0f;
1602 	fp[35]	= 0.0f;
1603 	fp[36]	= 29.0f;
1604 	fp[37]	= 30.0f;
1605 	fp[38]	= 31.0f;
1606 	fp[39]	= 0.0f;
1607 	fp[40]	= 32.0f;
1608 	fp[41]	= 33.0f;
1609 	fp[42]	= 34.0f;
1610 	fp[43]	= 0.0f;
1611 	fp[44]	= 35.0f;
1612 	fp[45]	= 36.0f;
1613 	fp[46]	= 37.0f;
1614 	fp[47]	= 0.0f;
1615 	fp[48]	= 38.0f;
1616 	fp[49]	= 39.0f;
1617 	fp[50]	= 40.0f;
1618 	fp[51]	= 0.0f;
1619 	fp[52]	= 41.0f;
1620 	fp[53]	= 42.0f;
1621 	fp[54]	= 43.0f;
1622 	fp[55]	= 0.0f;
1623 	fp[56]	= 44.0f;
1624 	fp[57]	= 45.0f;
1625 	fp[58]	= 46.0f;
1626 	fp[59]	= 0.0f;
1627 	fp[60]	= 47.0f;
1628 	fp[61]	= 48.0f;
1629 	fp[62]	= 49.0f;
1630 	fp[63]	= 50.0f;
1631 	fp[64]	= 51.0f;
1632 	fp[65]	= 52.0f;
1633 	fp[66]	= 53.0f;
1634 	fp[67]	= 54.0f;
1635 	fp[68]	= 55.0f;
1636 	fp[69]	= 56.0f;
1637 	fp[70]	= 57.0f;
1638 	fp[71]	= 58.0f;
1639 	fp[72]	= 59.0f;
1640 	fp[73]	= 60.0f;
1641 	fp[74]	= 61.0f;
1642 	fp[75]	= 62.0f;
1643 	fp[76]	= 63.0f;
1644 	fp[77]	= 64.0f;
1645 	fp[78]	= 65.0f;
1646 	fp[79]	= 66.0f;
1647 	fp[80]	= 67.0f;
1648 	fp[81]	= 68.0f;
1649 	fp[82]	= 69.0f;
1650 	fp[83]	= 70.0f;
1651 	fp[84]	= 71.0f;
1652 	fp[85]	= 72.0f;
1653 	fp[86]	= 73.0f;
1654 	fp[87]	= 74.0f;
1655 	fp[88]	= 75.0f;
1656 	fp[89]	= 76.0f;
1657 	fp[90]	= 77.0f;
1658 	fp[91]	= 78.0f;
1659 
1660 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
1661 			  "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1662 			  "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_input;" NL
1663 			  "layout(std430, binding = 1) buffer Output {" NL "  float data0[2];" NL "  float data1[3];" NL
1664 			  "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1665 			  "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1666 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1667 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1668 			  "  g_output.data2 = g_input.data2;" NL
1669 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1670 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1671 			  "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1672 			  "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1673 			  "  for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1674 			  "  for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1675 }
1676 
1677 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1678 {
GetInput(std::vector<GLubyte> & in_data)1679 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1680 	{
1681 		return GetInput430c6(in_data);
1682 	}
1683 };
1684 
1685 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1686 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1696 const char* GetInput430c7(std::vector<GLubyte>& in_data)
1697 {
1698 	in_data.resize(36 * 4);
1699 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1700 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1701 	ip[0]	 = 1;
1702 	ip[1]	 = 0;
1703 	ip[2]	 = 2;
1704 	ip[3]	 = 3;
1705 	fp[4]	 = 4.0f;
1706 	fp[5]	 = 0.0f;
1707 	fp[6]	 = 0.0f;
1708 	fp[7]	 = 0.0f;
1709 	fp[8]	 = 5.0f;
1710 	fp[9]	 = 6.0f;
1711 	fp[10]	= 7.0f;
1712 	fp[11]	= 0.0f;
1713 	fp[12]	= 8.0f;
1714 	fp[13]	= 0.0f;
1715 	fp[14]	= 0.0f;
1716 	fp[15]	= 0.0f;
1717 	fp[16]	= 9.0f;
1718 	fp[17]	= 10.0f;
1719 	fp[18]	= 11.0f;
1720 	fp[19]	= 0.0f;
1721 	ip[20]	= 12;
1722 	ip[21]	= 13;
1723 	ip[22]	= 14;
1724 	ip[23]	= 15;
1725 	fp[24]	= 16.0f;
1726 	fp[25]	= 0.0f;
1727 	fp[26]	= 0.0f;
1728 	fp[27]	= 0.0f;
1729 	fp[28]	= 17.0f;
1730 	fp[29]	= 18.0f;
1731 	fp[30]	= 19.0f;
1732 	fp[31]	= 0.0f;
1733 	ip[32]	= 20;
1734 	ip[33]	= 21;
1735 	ip[34]	= 22;
1736 	ip[35]	= 23;
1737 
1738 	return NL "struct Struct0 {" NL "  ivec2 m0;" NL "};" NL "struct Struct1 {" NL "  vec3 m0;" NL "};" NL
1739 			  "struct Struct3 {" NL "  int m0;" NL "};" NL "struct Struct2 {" NL "  float m0;" // offset = 0
1740 		NL "  Struct1 m1;"																	   // offset = 16
1741 		NL "  Struct0 m2;"																	   // offset = 32
1742 		NL "  int m3;"																		   // offset = 40
1743 		NL "  Struct3 m4;"																	   // offset = 44
1744 		NL "};" NL "layout(std430, binding = 0) buffer Input {" NL "  int data0;"			   // offset = 0
1745 		NL "  Struct0 data1;"																   // offset = 8
1746 		NL "  float data2;"																	   // offset = 16
1747 		NL "  Struct1 data3;"																   // offset = 32
1748 		NL "  Struct2 data4[2];"															   // offset = 48
1749 		NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  int data0;" NL "  Struct0 data1;" NL
1750 			  "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1751 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1752 			  "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
1753 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1754 }
1755 
1756 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1757 {
GetInput(std::vector<GLubyte> & in_data)1758 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1759 	{
1760 		return GetInput430c7(in_data);
1761 	}
1762 };
1763 
1764 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1765 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1775 const char* GetInput140c1(std::vector<GLubyte>& in_data)
1776 {
1777 	in_data.resize(5 * 4);
1778 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1779 	fp[0]	 = 1.0f;
1780 	fp[1]	 = 0.0f;
1781 	fp[2]	 = 0.0f;
1782 	fp[3]	 = 0.0f;
1783 	fp[4]	 = 2.0f;
1784 
1785 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "} g_input;" NL
1786 			  "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL "} g_output;" NL
1787 			  "void main() {" NL
1788 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1789 }
1790 
1791 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1792 {
GetInput(std::vector<GLubyte> & in_data)1793 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1794 	{
1795 		return GetInput140c1(in_data);
1796 	}
1797 };
1798 
1799 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1800 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1810 const char* GetInput140c2(std::vector<GLubyte>& in_data)
1811 {
1812 	in_data.resize(18 * 4);
1813 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1814 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1815 	fp[0]	 = 1.0f;
1816 	fp[1]	 = 0.0f;
1817 	fp[2]	 = 0.0f;
1818 	fp[3]	 = 0.0f;
1819 	fp[4]	 = 2.0f;
1820 	fp[5]	 = 0.0f;
1821 	fp[6]	 = 0.0f;
1822 	fp[7]	 = 0.0f;
1823 	fp[8]	 = 3.0f;
1824 	fp[9]	 = 0.0f;
1825 	fp[10]	= 0.0f;
1826 	fp[11]	= 0.0f;
1827 	fp[12]	= 4.0f;
1828 	fp[13]	= 0.0f;
1829 	fp[14]	= 0.0f;
1830 	fp[15]	= 0.0f;
1831 	ip[16]	= 5;
1832 	ip[17]	= 6;
1833 
1834 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1835 			  "  ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL
1836 			  "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1837 			  "  g_output.data0 = g_input.data0;" NL
1838 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1839 			  "  g_output.data2 = g_input.data2;" NL "}";
1840 }
1841 
1842 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1843 {
GetInput(std::vector<GLubyte> & in_data)1844 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1845 	{
1846 		return GetInput140c2(in_data);
1847 	}
1848 };
1849 
1850 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1851 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1861 const char* GetInput140c3(std::vector<GLubyte>& in_data)
1862 {
1863 	in_data.resize(29 * 4);
1864 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1865 	fp[0]	 = 1.0f;
1866 	fp[1]	 = 0.0f;
1867 	fp[2]	 = 0.0f;
1868 	fp[3]	 = 0.0f;
1869 	fp[4]	 = 2.0f;
1870 	fp[5]	 = 0.0f;
1871 	fp[6]	 = 0.0f;
1872 	fp[7]	 = 0.0f;
1873 	fp[8]	 = 3.0f;
1874 	fp[9]	 = 0.0f;
1875 	fp[10]	= 0.0f;
1876 	fp[11]	= 0.0f;
1877 	fp[12]	= 4.0f;
1878 	fp[13]	= 0.0f;
1879 	fp[14]	= 0.0f;
1880 	fp[15]	= 0.0f;
1881 	fp[16]	= 5.0f;
1882 	fp[17]	= 6.0f;
1883 	fp[18]	= 0.0f;
1884 	fp[19]	= 0.0f;
1885 	fp[20]	= 7.0f;
1886 	fp[21]	= 8.0f;
1887 	fp[22]	= 9.0f;
1888 	fp[23]	= 0.0f;
1889 	fp[24]	= 10.0f;
1890 	fp[25]	= 11.0f;
1891 	fp[26]	= 12.0f;
1892 	fp[27]	= 0.0f;
1893 	fp[28]	= 13.0f;
1894 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1895 			  "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1896 			  "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1897 			  "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1898 			  "  g_output.data0 = g_input.data0;" NL
1899 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1900 			  "  g_output.data2 = g_input.data2;" NL
1901 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1902 			  "  g_output.data4 = g_input.data4;" NL "}";
1903 }
1904 
1905 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1906 {
GetInput(std::vector<GLubyte> & in_data)1907 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1908 	{
1909 		return GetInput140c3(in_data);
1910 	}
1911 };
1912 
1913 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1914 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1924 const char* GetInput140c4(std::vector<GLubyte>& in_data)
1925 {
1926 	in_data.resize(25 * 4);
1927 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1928 	fp[0]	 = 1.0f;
1929 	fp[1]	 = 2.0f;
1930 	fp[2]	 = 0.0f;
1931 	fp[3]	 = 0.0f;
1932 	fp[4]	 = 3.0f;
1933 	fp[5]	 = 4.0f;
1934 	fp[6]	 = 0.0f;
1935 	fp[7]	 = 0.0f;
1936 	fp[8]	 = 5.0f;
1937 	fp[9]	 = 6.0f;
1938 	fp[10]	= 0.0f;
1939 	fp[11]	= 0.0f;
1940 	fp[12]	= 7.0f;
1941 	fp[13]	= 8.0f;
1942 	fp[14]	= 0.0f;
1943 	fp[15]	= 0.0f;
1944 	fp[16]	= 9.0f;
1945 	fp[17]	= 10.0f;
1946 	fp[18]	= 11.0f;
1947 	fp[19]	= 0.0f;
1948 	fp[20]	= 12.0f;
1949 	fp[21]	= 13.0f;
1950 	fp[22]	= 14.0f;
1951 	fp[23]	= 0.0f;
1952 	fp[24]	= 15.0f;
1953 
1954 	return NL "layout(std140, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1955 			  "  float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1956 			  "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1957 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1958 			  "  g_output.data2 = g_input.data2;" NL "}";
1959 }
1960 
1961 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
1962 {
GetInput(std::vector<GLubyte> & in_data)1963 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1964 	{
1965 		return GetInput140c4(in_data);
1966 	}
1967 };
1968 
1969 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
1970 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)1980 const char* GetInput140c5(std::vector<GLubyte>& in_data)
1981 {
1982 	in_data.resize(8 * 4);
1983 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1984 	fp[0]	 = 1.0f;
1985 	fp[1]	 = 2.0f;
1986 	fp[2]	 = 3.0f;
1987 	fp[3]	 = 4.0f;
1988 	fp[4]	 = 5.0f;
1989 	fp[5]	 = 6.0f;
1990 	fp[6]	 = 7.0f;
1991 	fp[7]	 = 8.0f;
1992 	return NL "layout(std140, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1993 			  "layout(std140, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1994 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1995 }
1996 
1997 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
1998 {
GetInput(std::vector<GLubyte> & in_data)1999 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2000 	{
2001 		return GetInput140c5(in_data);
2002 	}
2003 };
2004 
2005 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2006 {
GetInput(std::vector<GLubyte> & in_data)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 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2016 const char* GetInput140c6(std::vector<GLubyte>& in_data)
2017 {
2018 	in_data.resize(96 * 4);
2019 	float* fp = reinterpret_cast<float*>(&in_data[0]);
2020 	fp[0]	 = 1.0f;
2021 	fp[1]	 = 0.0f;
2022 	fp[2]	 = 0.0f;
2023 	fp[3]	 = 0.0f;
2024 	fp[4]	 = 2.0f;
2025 	fp[5]	 = 0.0f;
2026 	fp[6]	 = 0.0f;
2027 	fp[7]	 = 0.0f;
2028 	fp[8]	 = 3.0f;
2029 	fp[9]	 = 0.0f;
2030 	fp[10]	= 0.0f;
2031 	fp[11]	= 0.0f;
2032 	fp[12]	= 4.0f;
2033 	fp[13]	= 0.0f;
2034 	fp[14]	= 0.0f;
2035 	fp[15]	= 0.0f;
2036 	fp[16]	= 5.0f;
2037 	fp[17]	= 0.0f;
2038 	fp[18]	= 0.0f;
2039 	fp[19]	= 0.0f;
2040 	fp[20]	= 6.0f;
2041 	fp[21]	= 7.0f;
2042 	fp[22]	= 8.0f;
2043 	fp[23]	= 9.0f;
2044 	fp[24]	= 10.0f;
2045 	fp[25]	= 11.0f;
2046 	fp[26]	= 0.0f;
2047 	fp[27]	= 0.0f;
2048 	fp[28]	= 12.0f;
2049 	fp[29]	= 13.0f;
2050 	fp[30]	= 0.0f;
2051 	fp[31]	= 0.0f;
2052 	fp[32]	= 14.0f;
2053 	fp[33]	= 15.0f;
2054 	fp[34]	= 0.0f;
2055 	fp[35]	= 0.0f;
2056 	fp[36]	= 16.0f;
2057 	fp[37]	= 17.0f;
2058 	fp[38]	= 0.0f;
2059 	fp[39]	= 0.0f;
2060 	fp[40]	= 18.0f;
2061 	fp[41]	= 19.0f;
2062 	fp[42]	= 20.0f;
2063 	fp[43]	= 0.0f;
2064 	fp[44]	= 21.0f;
2065 	fp[45]	= 22.0f;
2066 	fp[46]	= 23.0f;
2067 	fp[47]	= 0.0f;
2068 	fp[48]	= 24.0f;
2069 	fp[49]	= 25.0f;
2070 	fp[50]	= 26.0f;
2071 	fp[51]	= 0.0f;
2072 	fp[52]	= 27.0f;
2073 	fp[53]	= 28.0f;
2074 	fp[54]	= 29.0f;
2075 	fp[55]	= 0.0f;
2076 	fp[56]	= 30.0f;
2077 	fp[57]	= 31.0f;
2078 	fp[58]	= 32.0f;
2079 	fp[59]	= 0.0f;
2080 	fp[60]	= 33.0f;
2081 	fp[61]	= 34.0f;
2082 	fp[62]	= 35.0f;
2083 	fp[63]	= 0.0f;
2084 	fp[64]	= 36.0f;
2085 	fp[65]	= 37.0f;
2086 	fp[66]	= 38.0f;
2087 	fp[67]	= 39.0f;
2088 	fp[68]	= 40.0f;
2089 	fp[69]	= 41.0f;
2090 	fp[70]	= 42.0f;
2091 	fp[71]	= 43.0f;
2092 	fp[72]	= 44.0f;
2093 	fp[73]	= 45.0f;
2094 	fp[74]	= 46.0f;
2095 	fp[75]	= 47.0f;
2096 	fp[76]	= 48.0f;
2097 	fp[77]	= 49.0f;
2098 	fp[78]	= 50.0f;
2099 	fp[79]	= 51.0f;
2100 	fp[80]	= 52.0f;
2101 	fp[81]	= 68.0f;
2102 	fp[82]	= 69.0f;
2103 	fp[83]	= 70.0f;
2104 	fp[84]	= 56.0f;
2105 	fp[85]	= 72.0f;
2106 	fp[86]	= 73.0f;
2107 	fp[87]	= 74.0f;
2108 	fp[88]	= 60.0f;
2109 	fp[89]	= 76.0f;
2110 	fp[90]	= 77.0f;
2111 	fp[91]	= 78.0f;
2112 	fp[92]	= 64.0f;
2113 	fp[93]	= 80.0f;
2114 	fp[94]	= 81.0f;
2115 	fp[95]	= 82.0f;
2116 
2117 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
2118 			  "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL "  mat4 data6[2];" NL
2119 			  "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL
2120 			  "  float data1[3];" NL "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL
2121 			  "  mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2122 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2123 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2124 			  "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
2125 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2126 			  "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2127 			  "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2128 }
2129 
2130 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2131 {
GetInput(std::vector<GLubyte> & in_data)2132 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2133 	{
2134 		return GetInput140c6(in_data);
2135 	}
2136 };
2137 
2138 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2139 {
GetInput(std::vector<GLubyte> & in_data)2140 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2141 	{
2142 		return GetInput140c6(in_data);
2143 	}
2144 };
2145 
2146 //-----------------------------------------------------------------------------
2147 // 1.8.1 BasicAtomicCase1
2148 //-----------------------------------------------------------------------------
2149 class BasicAtomicCase1VSFS : public ShaderStorageBufferObjectBase
2150 {
2151 	GLuint m_program;
2152 	GLuint m_storage_buffer[4];
2153 	GLuint m_vertex_array;
2154 	GLuint m_vertex_buffer;
2155 
Setup()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 
Run()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 
Cleanup()2305 	virtual long Cleanup()
2306 	{
2307 		glUseProgram(0);
2308 		glDeleteProgram(m_program);
2309 		glDeleteBuffers(4, m_storage_buffer);
2310 		glDeleteBuffers(1, &m_vertex_buffer);
2311 		glDeleteVertexArrays(1, &m_vertex_array);
2312 		return NO_ERROR;
2313 	}
2314 };
2315 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2316 {
2317 	GLuint m_program;
2318 	GLuint m_storage_buffer[2];
2319 
Setup()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 
Run()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 
Cleanup()2409 	virtual long Cleanup()
2410 	{
2411 		glUseProgram(0);
2412 		glDeleteProgram(m_program);
2413 		glDeleteBuffers(2, m_storage_buffer);
2414 		return NO_ERROR;
2415 	}
2416 };
2417 //-----------------------------------------------------------------------------
2418 // 1.8.3 BasicAtomicCase3
2419 //-----------------------------------------------------------------------------
2420 class BasicAtomicCase3VSFS : public ShaderStorageBufferObjectBase
2421 {
2422 	GLuint m_program;
2423 	GLuint m_storage_buffer;
2424 	GLuint m_vertex_array;
2425 	GLuint m_vertex_buffer;
2426 
Setup()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 
Run()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 
Cleanup()2522 	virtual long Cleanup()
2523 	{
2524 		glUseProgram(0);
2525 		glDeleteProgram(m_program);
2526 		glDeleteBuffers(1, &m_storage_buffer);
2527 		glDeleteBuffers(1, &m_vertex_buffer);
2528 		glDeleteVertexArrays(1, &m_vertex_array);
2529 		return NO_ERROR;
2530 	}
2531 };
2532 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2533 {
2534 	GLuint m_program;
2535 	GLuint m_storage_buffer;
2536 
Setup()2537 	virtual long Setup()
2538 	{
2539 		m_program		 = 0;
2540 		m_storage_buffer = 0;
2541 		return NO_ERROR;
2542 	}
2543 
Run()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 
Cleanup()2603 	virtual long Cleanup()
2604 	{
2605 		glUseProgram(0);
2606 		glDeleteProgram(m_program);
2607 		glDeleteBuffers(1, &m_storage_buffer);
2608 		return NO_ERROR;
2609 	}
2610 };
2611 
2612 //-----------------------------------------------------------------------------
2613 // 1.8.4 BasicAtomicCase4
2614 //-----------------------------------------------------------------------------
2615 class BasicAtomicCase4VSFS : public ShaderStorageBufferObjectBase
2616 {
2617 	GLuint m_program;
2618 	GLuint m_storage_buffer[2];
2619 	GLuint m_vertex_array;
2620 	GLuint m_vertex_buffer;
2621 
Setup()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 
Run()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 
Cleanup()2724 	virtual long Cleanup()
2725 	{
2726 		glUseProgram(0);
2727 		glDeleteProgram(m_program);
2728 		glDeleteBuffers(2, m_storage_buffer);
2729 		glDeleteBuffers(1, &m_vertex_buffer);
2730 		glDeleteVertexArrays(1, &m_vertex_array);
2731 		return NO_ERROR;
2732 	}
2733 };
2734 
2735 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2736 {
2737 	GLuint m_program;
2738 	GLuint m_storage_buffer[2];
2739 
Setup()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 
Run()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 
Cleanup()2811 	virtual long Cleanup()
2812 	{
2813 		glUseProgram(0);
2814 		glDeleteProgram(m_program);
2815 		glDeleteBuffers(2, m_storage_buffer);
2816 		return NO_ERROR;
2817 	}
2818 };
2819 //-----------------------------------------------------------------------------
2820 // 1.9.x BasicStdLayoutBase2
2821 //-----------------------------------------------------------------------------
2822 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
2823 {
2824 	GLuint m_program;
2825 	GLuint m_buffer[8];
2826 	GLuint m_vertex_array;
2827 
2828 	virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2829 
Setup()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 
Run()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 
Cleanup()2899 	virtual long Cleanup()
2900 	{
2901 		glDisable(GL_RASTERIZER_DISCARD);
2902 		glUseProgram(0);
2903 		glDeleteProgram(m_program);
2904 		glDeleteBuffers(8, m_buffer);
2905 		glDeleteVertexArrays(1, &m_vertex_array);
2906 		return NO_ERROR;
2907 	}
2908 };
2909 
2910 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
2911 {
2912 	GLuint m_program;
2913 	GLuint m_buffer[8];
2914 
2915 	virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
2916 
Setup()2917 	virtual long Setup()
2918 	{
2919 		m_program = 0;
2920 		memset(m_buffer, 0, sizeof(m_buffer));
2921 		return NO_ERROR;
2922 	}
2923 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])2993 const char* GetInputC1(std::vector<GLubyte> in_data[4])
2994 {
2995 	for (int i = 0; i < 4; ++i)
2996 	{
2997 		in_data[i].resize(1 * 4);
2998 		float* fp = reinterpret_cast<float*>(&in_data[i][0]);
2999 		fp[0]	 = (float)(i + 1) * 1.0f;
3000 	}
3001 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
3002 			  "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
3003 			  "void main() {" NL "    g_output[0].data0 = g_input[0].data0;" NL
3004 			  "    g_output[1].data0 = g_input[1].data0;" NL "    g_output[2].data0 = g_input[2].data0;" NL
3005 			  "    g_output[3].data0 = g_input[3].data0;" NL "}";
3006 }
3007 
3008 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3009 {
GetInput(std::vector<GLubyte> in_data[4])3010 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3011 	{
3012 		return GetInputC1(in_data);
3013 	}
3014 };
3015 
3016 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3017 {
GetInput(std::vector<GLubyte> in_data[4])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 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3027 const char* GetInputC2(std::vector<GLubyte> in_data[4])
3028 {
3029 	/* input 0, std140 */
3030 	{
3031 		in_data[0].resize(12 * 4);
3032 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3033 		fp[0]	 = 1.0f;
3034 		fp[1]	 = 0.0f;
3035 		fp[2]	 = 0.0f;
3036 		fp[3]	 = 0.0f;
3037 		fp[4]	 = 2.0f;
3038 		fp[5]	 = 0.0f;
3039 		fp[6]	 = 0.0f;
3040 		fp[7]	 = 0.0f;
3041 		fp[8]	 = 3.0f;
3042 		fp[9]	 = 0.0f;
3043 		fp[10]	= 0.0f;
3044 		fp[11]	= 0.0f;
3045 	}
3046 	/* input 1, std430 */
3047 	{
3048 		in_data[1].resize(3 * 4);
3049 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3050 		fp[0]	 = 4.0f;
3051 		fp[1]	 = 5.0f;
3052 		fp[2]	 = 6.0f;
3053 	}
3054 	/* input 2, std140 */
3055 	{
3056 		in_data[2].resize(12 * 4);
3057 		float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3058 		fp[0]	 = 7.0f;
3059 		fp[1]	 = 0.0f;
3060 		fp[2]	 = 0.0f;
3061 		fp[3]	 = 0.0f;
3062 		fp[4]	 = 8.0f;
3063 		fp[5]	 = 0.0f;
3064 		fp[6]	 = 0.0f;
3065 		fp[7]	 = 0.0f;
3066 		fp[8]	 = 9.0f;
3067 		fp[9]	 = 0.0f;
3068 		fp[10]	= 0.0f;
3069 		fp[11]	= 0.0f;
3070 	}
3071 	/* input 3, std430 */
3072 	{
3073 		in_data[3].resize(3 * 4);
3074 		float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3075 		fp[0]	 = 10.0f;
3076 		fp[1]	 = 11.0f;
3077 		fp[2]	 = 12.0f;
3078 	}
3079 	return NL "layout(std140, binding = 0) buffer Input0 {" NL "  float data0[3];" NL "} g_input0;" NL
3080 			  "layout(std430, binding = 1) buffer Input1 {" NL "  float data0[3];" NL "} g_input1;" NL
3081 			  "layout(std140, binding = 2) buffer Input2 {" NL "  float data0[3];" NL "} g_input2;" NL
3082 			  "layout(std430, binding = 3) buffer Input3 {" NL "  float data0[3];" NL "} g_input3;" NL
3083 			  "layout(std140, binding = 4) buffer Output0 {" NL "  float data0[3];" NL "} g_output0;" NL
3084 			  "layout(std430, binding = 5) buffer Output1 {" NL "  float data0[3];" NL "} g_output1;" NL
3085 			  "layout(std140, binding = 6) buffer Output2 {" NL "  float data0[3];" NL "} g_output2;" NL
3086 			  "layout(std430, binding = 7) buffer Output3 {" NL "  float data0[3];" NL "} g_output3;" NL
3087 			  "void main() {" NL
3088 			  "  for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3089 			  "  for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3090 			  "  for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3091 			  "  for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3092 }
3093 
3094 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3095 {
GetInput(std::vector<GLubyte> in_data[4])3096 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3097 	{
3098 		return GetInputC2(in_data);
3099 	}
3100 };
3101 
3102 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3103 {
GetInput(std::vector<GLubyte> in_data[4])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 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3113 const char* GetInputC3(std::vector<GLubyte> in_data[4])
3114 {
3115 	/* input 0, std140 */
3116 	{
3117 		in_data[0].resize(62 * 4);
3118 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3119 		int*   ip = reinterpret_cast<int*>(&in_data[0][0]);
3120 		ip[0]	 = 1;
3121 		ip[1]	 = 0;
3122 		ip[2]	 = 0;
3123 		ip[3]	 = 0;
3124 		fp[4]	 = 2.0f;
3125 		fp[5]	 = 0.0f;
3126 		fp[6]	 = 0.0f;
3127 		fp[7]	 = 0.0f;
3128 		fp[8]	 = 3.0f;
3129 		fp[9]	 = 0.0f;
3130 		fp[10]	= 0.0f;
3131 		fp[11]	= 0.0f;
3132 		fp[12]	= 4.0f;
3133 		fp[13]	= 0.0f;
3134 		fp[14]	= 0.0f;
3135 		fp[15]	= 0.0f;
3136 		fp[16]	= 5.0f;
3137 		fp[17]	= 0.0f;
3138 		fp[18]	= 0.0f;
3139 		fp[19]	= 0.0f;
3140 		fp[20]	= 6.0f;
3141 		fp[21]	= 0.0f;
3142 		fp[22]	= 0.0f;
3143 		fp[23]	= 0.0f;
3144 		fp[24]	= 7.0f;
3145 		fp[25]	= 8.0f;
3146 		fp[26]	= 0.0f;
3147 		fp[27]	= 0.0f;
3148 		fp[28]	= 9.0f;
3149 		fp[29]	= 10.0f;
3150 		fp[30]	= 0.0f;
3151 		fp[31]	= 0.0f;
3152 		fp[32]	= 11.0f;
3153 		fp[33]	= 12.0f;
3154 		fp[34]	= 0.0f;
3155 		fp[35]	= 0.0f;
3156 		fp[36]	= 13.0f;
3157 		fp[37]	= 0.0f;
3158 		fp[38]	= 0.0f;
3159 		fp[39]	= 0.0f;
3160 		fp[40]	= 14.0f;
3161 		fp[41]	= 0.0f;
3162 		fp[42]	= 0.0f;
3163 		fp[43]	= 0.0f;
3164 		fp[44]	= 15.0f;
3165 		fp[45]	= 0.0f;
3166 		fp[46]	= 0.0f;
3167 		fp[47]	= 0.0f;
3168 		ip[48]	= 16;
3169 		ip[49]	= 0;
3170 		ip[50]	= 0;
3171 		ip[51]	= 0;
3172 		ip[52]	= 17;
3173 		ip[53]	= 18;
3174 		ip[54]	= 19;
3175 		ip[55]	= 0;
3176 	}
3177 	/* input 1, std430 */
3178 	{
3179 		in_data[1].resize(30 * 4);
3180 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3181 		int*   ip = reinterpret_cast<int*>(&in_data[1][0]);
3182 		ip[0]	 = 1;
3183 		fp[1]	 = 2.0f;
3184 		fp[2]	 = 3.0f;
3185 		fp[3]	 = 4.0f;
3186 		fp[4]	 = 5.0f;
3187 		fp[5]	 = 6.0f;
3188 		fp[6]	 = 7.0f;
3189 		fp[7]	 = 8.0f;
3190 		fp[8]	 = 9.0f;
3191 		fp[9]	 = 10.0f;
3192 		fp[10]	= 11.0f;
3193 		fp[11]	= 12.0f;
3194 		fp[12]	= 13.0f;
3195 		fp[13]	= 14.0f;
3196 		fp[14]	= 15.0f;
3197 		ip[15]	= 16;
3198 		ip[16]	= 17;
3199 		ip[17]	= 18;
3200 		ip[18]	= 19;
3201 	}
3202 	/* input 2, std140 */
3203 	{
3204 		in_data[2].resize(5 * 4);
3205 		int* ip = reinterpret_cast<int*>(&in_data[2][0]);
3206 		ip[0]   = 1;
3207 		ip[1]   = 0;
3208 		ip[2]   = 0;
3209 		ip[3]   = 0;
3210 		ip[4]   = 2;
3211 	}
3212 	/* input 3, std430 */
3213 	{
3214 		in_data[3].resize(2 * 4);
3215 		int* ip = reinterpret_cast<int*>(&in_data[3][0]);
3216 		ip[0]   = 1;
3217 		ip[1]   = 2;
3218 	}
3219 	return NL "layout(std140, binding = 0) buffer Input0 {" NL "  int data0;"				//BA=4,  OF=[0]0,   next=4
3220 		NL "  float data1[5];"																//BA=16, OF=[4]16,  next=96
3221 		NL "  mat3x2 data2;"																//BA=16, OF=[24]96, next=144
3222 		NL "  float data3;"																	//BA=4,  OF=[36]144,next=148
3223 		NL "  float data4[2];"																//BA=16, OF=[40]160,next=192
3224 		NL "  int data5;"																	//BA=4,  OF=[48]192,next=196
3225 		NL "  ivec3 data6;"																	//BA=16, OF=[52]208
3226 		NL "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL "  int data0;" //BA=4, OF=[0],   next=[1]
3227 		NL "  float data1[5];"																//BA=4, OF=[1],   next=[6]
3228 		NL "  mat3x2 data2;"																//BA=8, OF=[6],   next=[12]
3229 		NL "  float data3;"																	//BA=4, OF=[12],  next=[13]
3230 		NL "  float data4[2];"																//BA=4, OF=[13],  next=[15]
3231 		NL "  int data5;"																	//BA=4, OF=[15],  next=[16]
3232 		NL "  ivec3 data6;"																	//BA=16,OF=[16]
3233 		NL "} g_input1;" NL "struct Struct0 {" NL "  int data0;" NL "};" NL
3234 			  "layout(std140, binding = 2) buffer Input2 {" NL "  int data0;" // offset 0
3235 		NL "  Struct0 data1;" // offset 16,  struct should be aligned to a multiple of 16 bytes
3236 		NL "} g_input2;" NL "layout(std430, binding = 3) buffer Input3 {" NL "  int data0;" // offset 0
3237 		NL "  Struct0 data1;"																// offset 4
3238 		NL "} g_input3;"
3239 
3240 		NL "layout(std140, binding = 4) buffer Output0 {" NL "  int data0;" NL "  float data1[5];" NL
3241 			  "  mat3x2 data2;" NL "  float data3;" NL "  float data4[2];" NL "  int data5;" NL "  ivec3 data6;" NL
3242 			  "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL "  int data0;" NL
3243 			  "  float data1[5];" NL "  mat3x2 data2;" NL "  float data3;" NL "  float data4[2];" NL "  int data5;" NL
3244 			  "  ivec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL "  int data0;" NL
3245 			  "  Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3246 			  "  int data0;" NL "  Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3247 			  "  g_output0.data0 = g_input0.data0;" NL
3248 			  "  for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3249 			  "  g_output0.data2 = g_input0.data2;" NL "  g_output0.data3 = g_input0.data3;" NL
3250 			  "  for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3251 			  "  g_output0.data5 = g_input0.data5;" NL "  g_output0.data6 = g_input0.data6;"
3252 
3253 		NL "  g_output1.data0 = g_input1.data0;" NL
3254 			  "  for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3255 			  "  g_output1.data2 = g_input1.data2;" NL "  g_output1.data3 = g_input1.data3;" NL
3256 			  "  for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3257 			  "  g_output1.data5 = g_input1.data5;" NL "  g_output1.data6 = g_input1.data6;"
3258 
3259 		NL "  g_output2.data0 = g_input2.data0;" NL "  g_output2.data1 = g_input2.data1;"
3260 
3261 		NL "  g_output3.data0 = g_input3.data0;" NL "  g_output3.data1 = g_input3.data1;" NL "}";
3262 }
3263 
3264 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3265 {
GetInput(std::vector<GLubyte> in_data[4])3266 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3267 	{
3268 		return GetInputC3(in_data);
3269 	}
3270 };
3271 
3272 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3273 {
GetInput(std::vector<GLubyte> in_data[4])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 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3283 const char* GetInputC4(std::vector<GLubyte> in_data[4])
3284 {
3285 	/* input 0, std140 */
3286 	{
3287 		in_data[0].resize(57 * 4);
3288 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3289 		int*   ip = reinterpret_cast<int*>(&in_data[0][0]);
3290 		ip[0]	 = 1;
3291 		ip[1]	 = 0;
3292 		ip[2]	 = 0;
3293 		ip[3]	 = 0;
3294 		ip[4]	 = 2;
3295 		ip[5]	 = 3;
3296 		ip[6]	 = 0;
3297 		ip[7]	 = 0;
3298 		ip[8]	 = 4;
3299 		ip[9]	 = 5;
3300 		ip[10]	= 0;
3301 		ip[11]	= 0;
3302 		fp[12]	= 6.0f;
3303 		fp[13]	= 0.0f;
3304 		fp[14]	= 0.0f;
3305 		fp[15]	= 0.0f;
3306 		fp[16]	= 7.0f;
3307 		fp[17]	= 8.0f;
3308 		fp[18]	= 0.0f;
3309 		fp[19]	= 0.0f;
3310 		ip[20]	= 9;
3311 		ip[21]	= 10;
3312 		ip[22]	= 11;
3313 		ip[23]	= 0;
3314 		fp[24]	= 12.0f;
3315 		fp[25]	= 13.0f;
3316 		fp[26]	= 0.0f;
3317 		fp[27]	= 0.0f;
3318 		ip[28]	= 14;
3319 		ip[29]	= 15;
3320 		ip[30]	= 16;
3321 		ip[31]	= 0;
3322 		fp[32]	= 17.0f;
3323 		fp[33]	= 0.0f;
3324 		fp[34]	= 0.0f;
3325 		fp[35]	= 0.0f;
3326 		ip[36]	= 18;
3327 		ip[37]	= 0;
3328 		ip[38]	= 0;
3329 		ip[39]	= 0;
3330 		ip[40]	= 19;
3331 		ip[41]	= 20;
3332 		ip[42]	= 0;
3333 		ip[43]	= 0;
3334 		ip[44]	= 21;
3335 		ip[45]	= 0;
3336 		ip[45]	= 0;
3337 		ip[45]	= 0;
3338 		fp[48]	= 22.0f;
3339 		fp[49]	= 23.0f;
3340 		fp[50]	= 0.0f;
3341 		fp[51]	= 0.0f;
3342 		ip[52]	= 24;
3343 		ip[53]	= 25;
3344 		ip[54]	= 26;
3345 		ip[55]	= 0;
3346 		fp[56]	= 27.0f;
3347 	}
3348 	/* input 1, std140 */
3349 	{
3350 		in_data[1].resize(57 * 4);
3351 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3352 		int*   ip = reinterpret_cast<int*>(&in_data[1][0]);
3353 		ip[0]	 = 101;
3354 		ip[1]	 = 0;
3355 		ip[2]	 = 0;
3356 		ip[3]	 = 0;
3357 		ip[4]	 = 102;
3358 		ip[5]	 = 103;
3359 		ip[6]	 = 0;
3360 		ip[7]	 = 0;
3361 		ip[8]	 = 104;
3362 		ip[9]	 = 105;
3363 		ip[10]	= 0;
3364 		ip[11]	= 0;
3365 		fp[12]	= 106.0f;
3366 		fp[13]	= 0.0f;
3367 		fp[14]	= 0.0f;
3368 		fp[15]	= 0.0f;
3369 		fp[16]	= 107.0f;
3370 		fp[17]	= 108.0f;
3371 		fp[18]	= 0.0f;
3372 		fp[19]	= 0.0f;
3373 		ip[20]	= 109;
3374 		ip[21]	= 110;
3375 		ip[22]	= 111;
3376 		ip[23]	= 0;
3377 		fp[24]	= 112.0f;
3378 		fp[25]	= 113.0f;
3379 		fp[26]	= 0.0f;
3380 		fp[27]	= 0.0f;
3381 		ip[28]	= 114;
3382 		ip[29]	= 115;
3383 		ip[30]	= 116;
3384 		ip[31]	= 0;
3385 		fp[32]	= 117.0f;
3386 		fp[33]	= 0.0f;
3387 		fp[34]	= 0.0f;
3388 		fp[35]	= 0.0f;
3389 		ip[36]	= 118;
3390 		ip[37]	= 0;
3391 		ip[38]	= 0;
3392 		ip[39]	= 0;
3393 		ip[40]	= 119;
3394 		ip[41]	= 120;
3395 		ip[42]	= 0;
3396 		ip[43]	= 0;
3397 		ip[44]	= 121;
3398 		ip[45]	= 0;
3399 		ip[45]	= 0;
3400 		ip[45]	= 0;
3401 		fp[48]	= 122.0f;
3402 		fp[49]	= 123.0f;
3403 		fp[50]	= 0.0f;
3404 		fp[51]	= 0.0f;
3405 		ip[52]	= 124;
3406 		ip[53]	= 125;
3407 		ip[54]	= 126;
3408 		ip[55]	= 0;
3409 		fp[56]	= 127.0f;
3410 	}
3411 	/* input 2, std430 */
3412 	{
3413 		in_data[2].resize(45 * 4);
3414 		float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3415 		int*   ip = reinterpret_cast<int*>(&in_data[2][0]);
3416 		ip[0]	 = 1000;
3417 		ip[1]	 = 0;
3418 		ip[2]	 = 1001;
3419 		ip[3]	 = 1002;
3420 		ip[4]	 = 1003;
3421 		ip[5]	 = 1004;
3422 		fp[6]	 = 1005.0f;
3423 		fp[7]	 = 0.0f;
3424 		fp[8]	 = 1006.0f;
3425 		fp[9]	 = 1007.0f;
3426 		fp[10]	= 0.0f;
3427 		fp[11]	= 0.0f;
3428 		ip[12]	= 1008;
3429 		ip[13]	= 1009;
3430 		ip[14]	= 1010;
3431 		ip[15]	= 0;
3432 		fp[16]	= 1011.0f;
3433 		fp[17]	= 1012.0f;
3434 		fp[18]	= 0.0f;
3435 		fp[19]	= 0.0f;
3436 		ip[20]	= 1013;
3437 		ip[21]	= 1014;
3438 		ip[22]	= 1015;
3439 		ip[23]	= 0;
3440 		fp[24]	= 1016.0f;
3441 		fp[25]	= 0.0f;
3442 		fp[26]	= 0.0f;
3443 		fp[27]	= 0.0f;
3444 		ip[28]	= 1017;
3445 		ip[29]	= 0;
3446 		ip[30]	= 1018;
3447 		ip[31]	= 1019;
3448 		ip[32]	= 1020;
3449 		ip[33]	= 0;
3450 		ip[34]	= 0;
3451 		ip[35]	= 0;
3452 		fp[36]	= 1021.0f;
3453 		fp[37]	= 1022.0f;
3454 		fp[38]	= 0.0f;
3455 		fp[39]	= 0.0f;
3456 		ip[40]	= 1023;
3457 		ip[41]	= 1024;
3458 		ip[42]	= 1025;
3459 		ip[43]	= 0;
3460 		fp[44]	= 1026.0f;
3461 	}
3462 	/* input 3, std430 */
3463 	{
3464 		in_data[3].resize(45 * 4);
3465 		float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3466 		int*   ip = reinterpret_cast<int*>(&in_data[3][0]);
3467 		ip[0]	 = 10000;
3468 		ip[1]	 = 0;
3469 		ip[2]	 = 10001;
3470 		ip[3]	 = 10002;
3471 		ip[4]	 = 10003;
3472 		ip[5]	 = 10004;
3473 		fp[6]	 = 10005.0f;
3474 		fp[7]	 = 0.0f;
3475 		fp[8]	 = 10006.0f;
3476 		fp[9]	 = 10007.0f;
3477 		fp[10]	= 0.0f;
3478 		fp[11]	= 0.0f;
3479 		ip[12]	= 10008;
3480 		ip[13]	= 10009;
3481 		ip[14]	= 10010;
3482 		ip[15]	= 0;
3483 		fp[16]	= 10011.0f;
3484 		fp[17]	= 10012.0f;
3485 		fp[18]	= 0.0f;
3486 		fp[19]	= 0.0f;
3487 		ip[20]	= 10013;
3488 		ip[21]	= 10014;
3489 		ip[22]	= 10015;
3490 		ip[23]	= 0;
3491 		fp[24]	= 10016.0f;
3492 		fp[25]	= 0.0f;
3493 		fp[26]	= 0.0f;
3494 		fp[27]	= 0.0f;
3495 		ip[28]	= 10017;
3496 		ip[29]	= 0;
3497 		ip[30]	= 10018;
3498 		ip[31]	= 10019;
3499 		ip[32]	= 10020;
3500 		ip[33]	= 0;
3501 		ip[34]	= 0;
3502 		ip[35]	= 0;
3503 		fp[36]	= 10021.0f;
3504 		fp[37]	= 10022.0f;
3505 		fp[38]	= 0.0f;
3506 		fp[39]	= 0.0f;
3507 		ip[40]	= 10023;
3508 		ip[41]	= 10024;
3509 		ip[42]	= 10025;
3510 		ip[43]	= 0;
3511 		fp[44]	= 10026.0f;
3512 	}
3513 
3514 	return NL
3515 		"struct Struct0 {" NL "  ivec2 data0;" NL "};" NL "struct Struct1 {" NL "  vec2 data0;" // offset 0
3516 		NL "  ivec3 data1;"																		// offset 16
3517 		NL "};" NL "struct Struct2 {" NL "  int data0;"											// offset 0
3518 		NL "  Struct0 data1;"														// offset std430 8, std140 16
3519 		NL "  int data2;"															// offset std430 16, std140 32
3520 		NL "  Struct1 data3;"														// offset std430 32, std140 48
3521 		NL "  float data4;"															// offset std430 64, std140 80
3522 		NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL "  int data0;" // offset 0
3523 		NL "  Struct0 data1[2];"													// offset 16
3524 		NL "  float data2;"															// offset 48
3525 		NL "  Struct1 data3[2];"													// offset 64
3526 		NL "  float data4;"															// offset 128
3527 		NL "  Struct2 data5;"														// offset 144
3528 		NL "} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL "  int data0;" // offset 0
3529 		NL "  Struct0 data1[2];"																 // offset 8
3530 		NL "  float data2;"																		 // offset 24
3531 		NL "  Struct1 data3[2];"																 // offset 32
3532 		NL "  float data4;"																		 // offset 96
3533 		NL "  Struct2 data5;"																	 // offset 112
3534 		NL "} g_input23[2];"
3535 
3536 		NL "layout(std140, binding = 4) buffer Output01 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3537 		"  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output01[2];" NL
3538 		"layout(std430, binding = 6) buffer Output23 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3539 		"  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output23[2];" NL NL
3540 		"void main() {" NL "  g_output01[0].data0 = g_input01[0].data0;" NL
3541 		"  for (int i = 0; i < g_input01[0].data1.length(); ++i) g_output01[0].data1[i] = g_input01[0].data1[i];" NL
3542 		"  g_output01[0].data2 = g_input01[0].data2;" NL "  g_output01[0].data3[0] = g_input01[0].data3[0];" NL
3543 		"  g_output01[0].data3[1] = g_input01[0].data3[1];" NL "  g_output01[0].data4 = g_input01[0].data4;" NL
3544 		"  g_output01[1].data0 = g_input01[1].data0;" NL
3545 		"  for (int i = 0; i < g_input01[1].data1.length(); ++i) g_output01[1].data1[i] = g_input01[1].data1[i];" NL
3546 		"  g_output01[1].data2 = g_input01[1].data2;" NL "  g_output01[1].data3[0] = g_input01[1].data3[0];" NL
3547 		"  g_output01[1].data3[1] = g_input01[1].data3[1];" NL "  g_output01[1].data4 = g_input01[1].data4;" NL
3548 		"  g_output01[0].data5 = g_input01[0].data5;" NL "  g_output01[1].data5 = g_input01[1].data5;" NL NL
3549 		"  g_output23[0].data0 = g_input23[0].data0;" NL
3550 		"  for (int i = 0; i < g_input23[0].data1.length(); ++i) g_output23[0].data1[i] = g_input23[0].data1[i];" NL
3551 		"  g_output23[0].data2 = g_input23[0].data2;" NL "  g_output23[0].data3[0] = g_input23[0].data3[0];" NL
3552 		"  g_output23[0].data3[1] = g_input23[0].data3[1];" NL "  g_output23[0].data4 = g_input23[0].data4;" NL
3553 		"  g_output23[1].data0 = g_input23[1].data0;" NL
3554 		"  for (int i = 0; i < g_input23[1].data1.length(); ++i) g_output23[1].data1[i] = g_input23[1].data1[i];" NL
3555 		"  g_output23[1].data2 = g_input23[1].data2;" NL "  g_output23[1].data3[0] = g_input23[1].data3[0];" NL
3556 		"  g_output23[1].data3[1] = g_input23[1].data3[1];" NL "  g_output23[1].data4 = g_input23[1].data4;" NL
3557 		"  g_output23[0].data5 = g_input23[0].data5;" NL "  g_output23[1].data5 = g_input23[1].data5;" NL "}";
3558 }
3559 
3560 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3561 {
GetInput(std::vector<GLubyte> in_data[4])3562 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3563 	{
3564 		return GetInputC4(in_data);
3565 	}
3566 };
3567 
3568 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3569 {
GetInput(std::vector<GLubyte> in_data[4])3570 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3571 	{
3572 		return GetInputC4(in_data);
3573 	}
3574 };
3575 
3576 //-----------------------------------------------------------------------------
3577 // 1.10.x BasicOperationsBase
3578 //-----------------------------------------------------------------------------
3579 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3580 {
3581 	GLuint m_program;
3582 	GLuint m_buffer[2];
3583 	GLuint m_vertex_array;
3584 
3585 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3586 
Setup()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 
Run()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 
Cleanup()3658 	virtual long Cleanup()
3659 	{
3660 		glDisable(GL_RASTERIZER_DISCARD);
3661 		glUseProgram(0);
3662 		glDeleteProgram(m_program);
3663 		glDeleteBuffers(2, m_buffer);
3664 		glDeleteVertexArrays(1, &m_vertex_array);
3665 		return NO_ERROR;
3666 	}
3667 };
3668 
3669 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3670 {
3671 	GLuint m_program;
3672 	GLuint m_buffer[2];
3673 
3674 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3675 
Setup()3676 	virtual long Setup()
3677 	{
3678 		m_program = 0;
3679 		memset(m_buffer, 0, sizeof(m_buffer));
3680 		return NO_ERROR;
3681 	}
3682 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3749 const char* GetInputOp1(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3750 {
3751 	/* input */
3752 	{
3753 		in_data.resize(16 * 9);
3754 		int*   ip = reinterpret_cast<int*>(&in_data[0]);
3755 		float* fp = reinterpret_cast<float*>(&in_data[0]);
3756 		ip[0]	 = 1;
3757 		ip[1]	 = 2;
3758 		ip[2]	 = 3;
3759 		ip[3]	 = 4; // data0
3760 		fp[4]	 = 1.0f;
3761 		fp[5]	 = 2.0f;
3762 		fp[6]	 = 3.0f;
3763 		fp[7]	 = 0.0f; // data1
3764 		ip[8]	 = 1;
3765 		ip[9]	 = 2;
3766 		ip[10]	= 3;
3767 		ip[11]	= 4; // data2
3768 		ip[12]	= 1;
3769 		ip[13]	= -2;
3770 		ip[14]	= 3;
3771 		ip[15]	= 4; // data3
3772 		fp[16]	= 1.0f;
3773 		fp[17]	= 2.0f;
3774 		fp[18]	= 3.0f;
3775 		fp[19]	= 4.0f; // data4
3776 		fp[20]	= 1.0f;
3777 		fp[21]	= 2.0f;
3778 		fp[22]	= 3.0f;
3779 		fp[23]	= 4.0f; // data5
3780 		fp[24]	= 1.0f;
3781 		fp[25]	= 2.0f;
3782 		fp[26]	= 3.0f;
3783 		fp[27]	= 4.0f; // data5
3784 		fp[28]	= 1.0f;
3785 		fp[29]	= 2.0f;
3786 		fp[30]	= 3.0f;
3787 		fp[31]	= 4.0f; // data5
3788 		fp[32]	= 1.0f;
3789 		fp[33]	= 0.0f;
3790 		fp[34]	= 0.0f;
3791 		fp[35]	= 4.0f; // data5
3792 	}
3793 	/* expected output */
3794 	{
3795 		out_data.resize(16 * 9);
3796 		int*   ip = reinterpret_cast<int*>(&out_data[0]);
3797 		float* fp = reinterpret_cast<float*>(&out_data[0]);
3798 		ip[0]	 = 4;
3799 		ip[1]	 = 3;
3800 		ip[2]	 = 2;
3801 		ip[3]	 = 1;
3802 		fp[4]	 = 3.0f;
3803 		fp[5]	 = 2.0f;
3804 		fp[6]	 = 1.0f;
3805 		fp[7]	 = 0.0f;
3806 		ip[8]	 = 4;
3807 		ip[9]	 = 1;
3808 		ip[10]	= 0;
3809 		ip[11]	= 3;
3810 		ip[12]	= 10;
3811 		ip[13]	= 4;
3812 		ip[14]	= -2;
3813 		ip[15]	= 20;
3814 		fp[16]	= 50.0f;
3815 		fp[17]	= 5.0f;
3816 		fp[18]	= 2.0f;
3817 		fp[19]	= 30.0f;
3818 		fp[20]	= 4.0f;
3819 		fp[21]	= 2.0f;
3820 		fp[22]	= 3.0f;
3821 		fp[23]	= 1.0f; // data5
3822 		fp[24]	= 4.0f;
3823 		fp[25]	= 3.0f;
3824 		fp[26]	= 2.0f;
3825 		fp[27]	= 1.0f; // data5
3826 		fp[28]	= 2.0f;
3827 		fp[29]	= 2.0f;
3828 		fp[30]	= 2.0f;
3829 		fp[31]	= 2.0f; // data5
3830 		fp[32]	= 4.0f;
3831 		fp[33]	= 0.0f;
3832 		fp[34]	= 0.0f;
3833 		fp[35]	= 1.0f; // data5
3834 	}
3835 
3836 	return NL "layout(std430, binding = 0) buffer Input {" NL "  ivec4 data0;" NL "  vec3 data1;" NL "  uvec4 data2;" NL
3837 			  "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_input;" NL
3838 			  "layout(std430, binding = 1) buffer Output {" NL "  ivec4 data0;" NL "  vec3 data1;" NL
3839 			  "  uvec4 data2;" NL "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_output;" NL
3840 			  "uniform vec3 g_value0;" NL "uniform int g_index1;" NL "void main() {" NL "  int index0 = 0;" NL
3841 			  "  g_output.data0.wzyx = g_input.data0;" NL "  g_output.data1 = g_input.data1.zyx;" NL
3842 			  "  g_output.data2.xwy = g_input.data2.wzx;" NL "  g_output.data3.xw = ivec2(10, 20);" NL
3843 			  "  g_output.data3.zy = g_input.data3.yw;" NL "  g_output.data4.wx = g_value0.xz;" // w == 10.0, x == 30.0
3844 		NL "  g_output.data4.wx += g_value0.yy;"												// w == 30.0, x == 50.0
3845 		NL "  g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;"							// y == 5.0, z == 2.0
3846 		NL "  g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
3847 			  "  g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
3848 			  "  g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
3849 			  "  g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
3850 }
3851 
3852 class BasicOperationsCase1VS : public BasicOperationsBaseVS
3853 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3854 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3855 	{
3856 		return GetInputOp1(in_data, out_data);
3857 	}
3858 };
3859 
3860 class BasicOperationsCase1CS : public BasicOperationsBaseCS
3861 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)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 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3871 const char* GetInputOp2(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3872 {
3873 	/* input */
3874 	{
3875 		in_data.resize(16 * 8);
3876 		float* fp = reinterpret_cast<float*>(&in_data[0]);
3877 		fp[0]	 = 1.0f;
3878 		fp[1]	 = 0.0f;
3879 		fp[2]	 = 0.0f;
3880 		fp[3]	 = 0.0f;
3881 		fp[4]	 = 0.0f;
3882 		fp[5]	 = 1.0f;
3883 		fp[6]	 = 0.0f;
3884 		fp[7]	 = 0.0f;
3885 		fp[8]	 = 0.0f;
3886 		fp[9]	 = 0.0f;
3887 		fp[10]	= 1.0f;
3888 		fp[11]	= 0.0f;
3889 		fp[12]	= 0.0f;
3890 		fp[13]	= 0.0f;
3891 		fp[14]	= 0.0f;
3892 		fp[15]	= 1.0f;
3893 
3894 		fp[16] = 2.0f;
3895 		fp[17] = 0.0f;
3896 		fp[18] = 0.0f;
3897 		fp[19] = 0.0f;
3898 		fp[20] = 0.0f;
3899 		fp[21] = 3.0f;
3900 		fp[22] = 0.0f;
3901 		fp[23] = 0.0f;
3902 		fp[24] = 0.0f;
3903 		fp[25] = 0.0f;
3904 		fp[26] = 4.0f;
3905 		fp[27] = 0.0f;
3906 		fp[28] = 0.0f;
3907 		fp[29] = 0.0f;
3908 		fp[30] = 0.0f;
3909 		fp[31] = 5.0f;
3910 	}
3911 	/* expected output */
3912 	{
3913 		out_data.resize(16 * 5);
3914 		float* fp = reinterpret_cast<float*>(&out_data[0]);
3915 		fp[0]	 = 2.0f;
3916 		fp[1]	 = 0.0f;
3917 		fp[2]	 = 0.0f;
3918 		fp[3]	 = 0.0f;
3919 		fp[4]	 = 0.0f;
3920 		fp[5]	 = 3.0f;
3921 		fp[6]	 = 0.0f;
3922 		fp[7]	 = 0.0f;
3923 		fp[8]	 = 0.0f;
3924 		fp[9]	 = 0.0f;
3925 		fp[10]	= 4.0f;
3926 		fp[11]	= 0.0f;
3927 		fp[12]	= 0.0f;
3928 		fp[13]	= 0.0f;
3929 		fp[14]	= 0.0f;
3930 		fp[15]	= 5.0f;
3931 
3932 		fp[16] = 0.0f;
3933 		fp[17] = 1.0f;
3934 		fp[18] = 4.0f;
3935 		fp[19] = 0.0f;
3936 	}
3937 	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4 data0;" NL "  mat4 data1;" NL "} g_input;" NL
3938 			  "layout(std430, binding = 1) buffer Output {" NL "  mat4 data0;" NL "  vec4 data1;" NL "} g_output;" NL
3939 			  "uniform int g_index2;" NL "void main() {" NL
3940 			  "  g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
3941 			  "  g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
3942 }
3943 
3944 class BasicOperationsCase2VS : public BasicOperationsBaseVS
3945 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3947 	{
3948 		return GetInputOp2(in_data, out_data);
3949 	}
3950 };
3951 
3952 class BasicOperationsCase2CS : public BasicOperationsBaseCS
3953 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3954 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3955 	{
3956 		return GetInputOp2(in_data, out_data);
3957 	}
3958 };
3959 
3960 //-----------------------------------------------------------------------------
3961 // 1.11.x BasicStdLayoutBase3
3962 //-----------------------------------------------------------------------------
3963 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
3964 {
3965 	GLuint m_program;
3966 	GLuint m_buffer[4];
3967 	GLuint m_vertex_array;
3968 
3969 	virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
3970 
Setup()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 
Run()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 
Cleanup()4053 	virtual long Cleanup()
4054 	{
4055 		glDisable(GL_RASTERIZER_DISCARD);
4056 		glUseProgram(0);
4057 		glDeleteProgram(m_program);
4058 		glDeleteBuffers(4, m_buffer);
4059 		glDeleteVertexArrays(1, &m_vertex_array);
4060 		return NO_ERROR;
4061 	}
4062 };
4063 
4064 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4065 {
4066 	GLuint m_program;
4067 	GLuint m_buffer[4];
4068 
4069 	virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
4070 
Setup()4071 	virtual long Setup()
4072 	{
4073 		m_program = 0;
4074 		memset(m_buffer, 0, sizeof(m_buffer));
4075 		return NO_ERROR;
4076 	}
4077 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4155 const char* GetInputUBO1(std::vector<GLubyte> in_data[2])
4156 {
4157 	/* UBO */
4158 	{
4159 		in_data[0].resize(12 * 4);
4160 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4161 		fp[0]	 = 1.0f;
4162 		fp[1]	 = 0.0f;
4163 		fp[2]	 = 0.0f;
4164 		fp[3]	 = 0.0f;
4165 		fp[4]	 = 2.0f;
4166 		fp[5]	 = 0.0f;
4167 		fp[6]	 = 0.0f;
4168 		fp[7]	 = 0.0f;
4169 		fp[8]	 = 3.0f;
4170 		fp[9]	 = 0.0f;
4171 		fp[10]	= 0.0f;
4172 		fp[11]	= 0.0f;
4173 	}
4174 	/* SSBO */
4175 	{
4176 		in_data[1].resize(3 * 4);
4177 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4178 		fp[0]	 = 1.0f;
4179 		fp[1]	 = 2.0f;
4180 		fp[2]	 = 3.0f;
4181 	}
4182 
4183 	return NL
4184 		"layout(std140, binding = 0) uniform InputUBO {" NL "  float data0;" NL "  float data1[2];" NL
4185 		"} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL "  float data0;" NL
4186 		"  float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4187 		"  float data0;" NL "  float data1[2];" NL "} g_output_ubo;" NL
4188 		"layout(std430, binding = 2) buffer OutputSSBO {" NL "  float data0;" NL "  float data1[2];" NL
4189 		"} g_output_ssbo;" NL "void main() {" NL "  g_output_ubo.data0 = g_input_ubo.data0;" NL
4190 		"  for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4191 		"  g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4192 		"  for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4193 		"}";
4194 }
4195 
4196 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4197 {
GetInput(std::vector<GLubyte> in_data[2])4198 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4199 	{
4200 		return GetInputUBO1(in_data);
4201 	}
4202 };
4203 
4204 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4205 {
GetInput(std::vector<GLubyte> in_data[2])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 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4215 const char* GetInputUBO2(std::vector<GLubyte> in_data[2])
4216 {
4217 	/* UBO */
4218 	{
4219 		in_data[0].resize(280 * 4);
4220 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4221 		int*   ip = reinterpret_cast<int*>(&in_data[0][0]);
4222 		fp[0]	 = 1.0f;
4223 		fp[1]	 = 2.0f;
4224 		fp[2]	 = 3.0f;
4225 		fp[3]	 = 4.0f;
4226 		fp[4]	 = 5.0f;
4227 		fp[5]	 = 6.0f;
4228 		fp[6]	 = 7.0f;
4229 		fp[8]	 = 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 
4366 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4367 {
GetInput(std::vector<GLubyte> in_data[2])4368 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4369 	{
4370 		return GetInputUBO2(in_data);
4371 	}
4372 };
4373 
4374 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4375 {
GetInput(std::vector<GLubyte> in_data[2])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 //-----------------------------------------------------------------------------
4385 class 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 
Equal(float a,float b)4393 	static bool Equal(float a, float b)
4394 	{
4395 		return fabsf(a - b) < 0.001f;
4396 	}
4397 
Setup()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 
Run()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 
Cleanup()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 
4476 class 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 
Equal(float a,float b)4483 	static bool Equal(float a, float b)
4484 	{
4485 		return fabsf(a - b) < 0.001f;
4486 	}
4487 
Setup()4488 	virtual long Setup()
4489 	{
4490 		m_program = 0;
4491 		memset(m_buffer, 0, sizeof(m_buffer));
4492 		return NO_ERROR;
4493 	}
4494 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4558 const 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 
4579 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4580 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4581 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4582 	{
4583 		return GetInputM1(in, expected);
4584 	}
4585 };
4586 
4587 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4588 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4598 const 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 
4627 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4628 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4629 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4630 	{
4631 		return GetInputM2(in, expected);
4632 	}
4633 };
4634 
4635 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
4636 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4646 const 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 
4675 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4676 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4677 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4678 	{
4679 		return GetInputM3(in, expected);
4680 	}
4681 };
4682 
4683 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4684 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4694 const 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 
4723 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4724 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4725 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4726 	{
4727 		return GetInputM4(in, expected);
4728 	}
4729 };
4730 
4731 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4732 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4742 const 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 
4770 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4771 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4772 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4773 	{
4774 		return GetInputM5(in, expected);
4775 	}
4776 };
4777 
4778 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4779 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4789 const 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 
4818 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
4819 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4820 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4821 	{
4822 		return GetInputM6(in, expected);
4823 	}
4824 };
4825 
4826 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
4827 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)4837 const 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 
4865 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
4866 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4867 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4868 	{
4869 		return GetInputM7(in, expected);
4870 	}
4871 };
4872 
4873 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
4874 {
GetInput(std::vector<float> & in,std::vector<float> & expected)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 //-----------------------------------------------------------------------------
4884 class AdvancedSwitchBuffersVS : public ShaderStorageBufferObjectBase
4885 {
PassCriteria()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 
Setup()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 
Run()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 
Cleanup()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 };
5027 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5028 {
5029 	GLuint m_program;
5030 	GLuint m_storage_buffer[6];
5031 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
5148 class 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 
GenSource(int binding)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 
Setup()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 
Run()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 
Cleanup()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 };
5268 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5269 {
5270 	GLuint m_program[4];
5271 	GLuint m_storage_buffer[5];
5272 
Setup()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 
GenSource(int binding)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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
5362 class 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 
Setup()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 
Run()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 
Cleanup()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 
5502 class 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 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
5624 class 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 
Setup()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 
Run()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 
Cleanup()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 
5767 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
5768 {
5769 	GLuint m_program;
5770 	GLuint m_storage_buffer[5];
5771 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
5949 class 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 
Setup()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 
Run()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 
Cleanup()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 
6122 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6123 {
6124 	GLuint m_program;
6125 	GLuint m_storage_buffer[5];
6126 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
6230 class AdvancedReadWriteCase1VSFS : public ShaderStorageBufferObjectBase
6231 {
6232 	GLuint m_program;
6233 	GLuint m_storage_buffer;
6234 	GLuint m_vertex_array;
6235 	GLuint m_vertex_buffer;
6236 
Setup()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 
Run()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 
Cleanup()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 };
6333 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6334 {
6335 	GLuint m_program;
6336 	GLuint m_storage_buffer;
6337 
Setup()6338 	virtual long Setup()
6339 	{
6340 		m_program		 = 0;
6341 		m_storage_buffer = 0;
6342 		return NO_ERROR;
6343 	}
6344 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
6432 class 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 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
6560 class AdvancedUsageSyncVSFS : public ShaderStorageBufferObjectBase
6561 {
6562 	GLuint m_program;
6563 	GLuint m_storage_buffer[7];
6564 	GLuint m_vertex_array;
6565 
Setup()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 
Run()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 
Cleanup()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 };
6807 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
6808 {
6809 	GLuint m_program;
6810 	GLuint m_storage_buffer[7];
6811 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
7049 class AdvancedUsageOperatorsVS : public ShaderStorageBufferObjectBase
7050 {
7051 	GLuint m_program;
7052 	GLuint m_storage_buffer[2];
7053 	GLuint m_vertex_array;
7054 
Setup()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 
Run()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 
Cleanup()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 };
7156 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7157 {
7158 	GLuint m_program;
7159 	GLuint m_storage_buffer[2];
7160 
Setup()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 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
7237 template <int stage>
7238 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7239 {
7240 	GLuint m_program;
7241 	GLuint m_storage_buffer[4];
7242 	GLuint m_vertex_array;
7243 
Setup()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 
Cleanup()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 	}
BuildShaderPT(int st)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 	}
BuildShader()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 
Run()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 
7383 class 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 
Setup()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 
Cleanup()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 	}
BuildShaderPT(int stagept)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 	}
BuildShader()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 
Run()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 
7663 public:
7664 	int  stage;
7665 	int  etype;
7666 	int  layout;
7667 	bool other_members;
7668 	int  bind_seq;
7669 	bool length_as_index;
7670 
AdvancedUnsizedArrayLength2()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 
7688 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
7689 {
7690 public:
SetPath()7691 	virtual void SetPath()
7692 	{
7693 		length_as_index = true;
7694 	}
7695 };
7696 
7697 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
7698 {
7699 public:
SetPath()7700 	virtual void SetPath()
7701 	{
7702 		bind_seq = bindbaseafter;
7703 	}
7704 };
7705 
7706 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
7707 {
7708 public:
SetPath()7709 	virtual void SetPath()
7710 	{
7711 		bind_seq = bindrangeoffset;
7712 	}
7713 };
7714 
7715 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
7716 {
7717 public:
SetPath()7718 	virtual void SetPath()
7719 	{
7720 		bind_seq = bindrangesize;
7721 	}
7722 };
7723 
7724 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
7725 {
7726 public:
SetPath()7727 	virtual void SetPath()
7728 	{
7729 		etype = vector;
7730 	}
7731 };
7732 
7733 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
7734 {
7735 public:
SetPath()7736 	virtual void SetPath()
7737 	{
7738 		etype = matrix_cm;
7739 	}
7740 };
7741 
7742 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
7743 {
7744 public:
SetPath()7745 	virtual void SetPath()
7746 	{
7747 		etype = matrix_rm;
7748 	}
7749 };
7750 
7751 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
7752 {
7753 public:
SetPath()7754 	virtual void SetPath()
7755 	{
7756 		etype = structure;
7757 	}
7758 };
7759 
7760 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
7761 {
7762 public:
SetPath()7763 	virtual void SetPath()
7764 	{
7765 		stage  = compute;
7766 		layout = std140;
7767 	}
7768 };
7769 
7770 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
7771 {
7772 public:
SetPath()7773 	virtual void SetPath()
7774 	{
7775 		etype  = matrix_cm;
7776 		layout = std140;
7777 	}
7778 };
7779 
7780 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
7781 {
7782 public:
SetPath()7783 	virtual void SetPath()
7784 	{
7785 		etype  = matrix_rm;
7786 		layout = std140;
7787 	}
7788 };
7789 
7790 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
7791 {
7792 public:
SetPath()7793 	virtual void SetPath()
7794 	{
7795 		etype  = structure;
7796 		layout = std140;
7797 	}
7798 };
7799 
7800 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
7801 {
7802 public:
SetPath()7803 	virtual void SetPath()
7804 	{
7805 		etype  = vector;
7806 		layout = packed;
7807 	}
7808 };
7809 
7810 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
7811 {
7812 public:
SetPath()7813 	virtual void SetPath()
7814 	{
7815 		etype  = matrix_cm;
7816 		layout = packed;
7817 	}
7818 };
7819 
7820 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
7821 {
7822 public:
SetPath()7823 	virtual void SetPath()
7824 	{
7825 		etype  = matrix_rm;
7826 		layout = shared;
7827 	}
7828 };
7829 
7830 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
7831 {
7832 public:
SetPath()7833 	virtual void SetPath()
7834 	{
7835 		stage  = fragment;
7836 		etype  = vector;
7837 		layout = std430;
7838 	}
7839 };
7840 
7841 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7842 {
7843 public:
SetPath()7844 	virtual void SetPath()
7845 	{
7846 		stage		  = fragment;
7847 		etype		  = matrix_cm;
7848 		layout		  = std430;
7849 		other_members = true;
7850 	}
7851 };
7852 
7853 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
7854 {
7855 public:
SetPath()7856 	virtual void SetPath()
7857 	{
7858 		stage  = fragment;
7859 		etype  = matrix_rm;
7860 		layout = std140;
7861 	}
7862 };
7863 
7864 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
7865 {
7866 public:
SetPath()7867 	virtual void SetPath()
7868 	{
7869 		stage  = fragment;
7870 		etype  = structure;
7871 		layout = std140;
7872 	}
7873 };
7874 
7875 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7876 {
7877 public:
SetPath()7878 	virtual void SetPath()
7879 	{
7880 		stage		  = vertex;
7881 		etype		  = vector;
7882 		layout		  = std430;
7883 		other_members = true;
7884 	}
7885 };
7886 
7887 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
7888 {
7889 public:
SetPath()7890 	virtual void SetPath()
7891 	{
7892 		stage  = vertex;
7893 		etype  = matrix_cm;
7894 		layout = std140;
7895 	}
7896 };
7897 
7898 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
7899 {
7900 public:
SetPath()7901 	virtual void SetPath()
7902 	{
7903 		stage  = vertex;
7904 		etype  = matrix_rm;
7905 		layout = packed;
7906 	}
7907 };
7908 
7909 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
7910 {
7911 public:
SetPath()7912 	virtual void SetPath()
7913 	{
7914 		stage  = vertex;
7915 		etype  = structure;
7916 		layout = std140;
7917 	}
7918 };
7919 
7920 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
7921 {
7922 public:
SetPath()7923 	virtual void SetPath()
7924 	{
7925 		etype		  = vector;
7926 		other_members = true;
7927 	}
7928 };
7929 
7930 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
7931 {
7932 public:
SetPath()7933 	virtual void SetPath()
7934 	{
7935 		etype		  = matrix_cm;
7936 		other_members = true;
7937 	}
7938 };
7939 
7940 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
7941 {
7942 public:
SetPath()7943 	virtual void SetPath()
7944 	{
7945 		etype		  = matrix_rm;
7946 		layout		  = std140;
7947 		other_members = true;
7948 	}
7949 };
7950 
7951 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
7952 {
7953 public:
SetPath()7954 	virtual void SetPath()
7955 	{
7956 		etype		  = structure;
7957 		other_members = true;
7958 	}
7959 };
7960 
7961 //-----------------------------------------------------------------------------
7962 // 2.8 AdvancedMatrix
7963 //-----------------------------------------------------------------------------
7964 class 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 
Setup()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 
Run()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 
Cleanup()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 
8084 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8085 {
8086 	GLuint m_program;
8087 	GLuint m_storage_buffer;
8088 
Setup()8089 	virtual long Setup()
8090 	{
8091 		m_program		 = 0;
8092 		m_storage_buffer = 0;
8093 		return NO_ERROR;
8094 	}
8095 
Run()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 
Cleanup()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 //-----------------------------------------------------------------------------
8161 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8162 {
Run()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 //-----------------------------------------------------------------------------
8213 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8214 {
Shader1(int binding)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 
Shader2(int binding)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 
Run()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 	}
Compile(const std::string & source)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 //-----------------------------------------------------------------------------
8360 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8361 {
Run()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 	}
Link(const std::string & cs0,const std::string & cs1)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 
ShaderStorageBufferObjectTests(deqp::Context & context)8456 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
8457 	: TestCaseGroup(context, "shader_storage_buffer_object", "")
8458 {
8459 }
8460 
~ShaderStorageBufferObjectTests(void)8461 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
8462 {
8463 }
8464 
init()8465 void 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