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