• 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 "gl4cShaderStorageBufferObjectTests.hpp"
25 #include "glwEnums.hpp"
26 #include "tcuMatrix.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include <assert.h>
29 #include <cmath>
30 #include <cstdarg>
31 
32 namespace gl4cts
33 {
34 using namespace glw;
35 
36 namespace
37 {
38 typedef tcu::Vec2  vec2;
39 typedef tcu::Vec3  vec3;
40 typedef tcu::Vec4  vec4;
41 typedef tcu::IVec4 ivec4;
42 typedef tcu::UVec4 uvec4;
43 typedef tcu::Mat4  mat4;
44 
45 enum ShaderStage
46 {
47 	vertex,
48 	fragment,
49 	compute
50 };
51 
52 enum BufferLayout
53 {
54 	std140,
55 	std430,
56 	shared,
57 	packed
58 };
59 
60 enum ElementType
61 {
62 	vector,
63 	matrix_cm,
64 	matrix_rm,
65 	structure
66 };
67 
68 enum BindingSeq
69 {
70 	bindbasebefore,
71 	bindbaseafter,
72 	bindrangeoffset,
73 	bindrangesize
74 };
75 
76 const char* const kGLSLVer = "#version 430 core\n";
77 
78 class ShaderStorageBufferObjectBase : public deqp::SubcaseBase
79 {
Title()80 	virtual std::string Title()
81 	{
82 		return "";
83 	}
84 
Purpose()85 	virtual std::string Purpose()
86 	{
87 		return "";
88 	}
89 
Method()90 	virtual std::string Method()
91 	{
92 		return "";
93 	}
94 
PassCriteria()95 	virtual std::string PassCriteria()
96 	{
97 		return "";
98 	}
99 
100 public:
SupportedInVS(int requiredVS)101 	bool SupportedInVS(int requiredVS)
102 	{
103 		GLint blocksVS;
104 		glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
105 		if (blocksVS >= requiredVS)
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 			OutputNotSupported(reason.str());
113 			return false;
114 		}
115 	}
116 
SupportedInTCS(int requiredTCS)117 	bool SupportedInTCS(int requiredTCS)
118 	{
119 		GLint blocksTCS;
120 		glGetIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &blocksTCS);
121 		if (blocksTCS >= requiredTCS)
122 			return true;
123 		else
124 		{
125 			std::ostringstream reason;
126 			reason << "Required " << requiredTCS << " TCS storage blocks but only " << blocksTCS << " available."
127 				   << std::endl;
128 			OutputNotSupported(reason.str());
129 			return false;
130 		}
131 	}
132 
SupportedInTES(int requiredTES)133 	bool SupportedInTES(int requiredTES)
134 	{
135 		GLint blocksTES;
136 		glGetIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &blocksTES);
137 		if (blocksTES >= requiredTES)
138 			return true;
139 		else
140 		{
141 			std::ostringstream reason;
142 			reason << "Required " << requiredTES << " TES storage blocks but only " << blocksTES << " available."
143 				   << std::endl;
144 			OutputNotSupported(reason.str());
145 			return false;
146 		}
147 	}
148 
SupportedInGS(int requiredGS)149 	bool SupportedInGS(int requiredGS)
150 	{
151 		GLint blocksGS;
152 		glGetIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &blocksGS);
153 		if (blocksGS >= requiredGS)
154 			return true;
155 		else
156 		{
157 			std::ostringstream reason;
158 			reason << "Required " << requiredGS << " GS storage blocks but only " << blocksGS << " available."
159 				   << std::endl;
160 			OutputNotSupported(reason.str());
161 			return false;
162 		}
163 	}
164 
getWindowWidth()165 	int getWindowWidth()
166 	{
167 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
168 		return renderTarget.getWidth();
169 	}
170 
getWindowHeight()171 	int getWindowHeight()
172 	{
173 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
174 		return renderTarget.getHeight();
175 	}
176 
ColorEqual(const vec3 & c0,const vec3 & c1,const vec4 & epsilon)177 	inline bool ColorEqual(const vec3& c0, const vec3& c1, const vec4& epsilon)
178 	{
179 		if (fabs(c0[0] - c1[0]) > epsilon[0])
180 			return false;
181 		if (fabs(c0[1] - c1[1]) > epsilon[1])
182 			return false;
183 		if (fabs(c0[2] - c1[2]) > epsilon[2])
184 			return false;
185 		return true;
186 	}
187 
CheckProgram(GLuint program)188 	bool CheckProgram(GLuint program)
189 	{
190 		GLint status;
191 		glGetProgramiv(program, GL_LINK_STATUS, &status);
192 
193 		if (status == GL_FALSE)
194 		{
195 			GLint attached_shaders;
196 			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
197 
198 			if (attached_shaders > 0)
199 			{
200 				std::vector<GLuint> shaders(attached_shaders);
201 				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
202 
203 				for (GLint i = 0; i < attached_shaders; ++i)
204 				{
205 					GLenum type;
206 					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
207 
208 					switch (type)
209 					{
210 					case GL_VERTEX_SHADER:
211 						m_context.getTestContext().getLog()
212 							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
213 						break;
214 					case GL_TESS_CONTROL_SHADER:
215 						m_context.getTestContext().getLog()
216 							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
217 							<< tcu::TestLog::EndMessage;
218 						break;
219 					case GL_TESS_EVALUATION_SHADER:
220 						m_context.getTestContext().getLog()
221 							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
222 							<< tcu::TestLog::EndMessage;
223 						break;
224 					case GL_GEOMETRY_SHADER:
225 						m_context.getTestContext().getLog()
226 							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
227 						break;
228 					case GL_FRAGMENT_SHADER:
229 						m_context.getTestContext().getLog()
230 							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
231 						break;
232 					case GL_COMPUTE_SHADER:
233 						m_context.getTestContext().getLog()
234 							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
235 						break;
236 					default:
237 						m_context.getTestContext().getLog()
238 							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
239 						break;
240 					}
241 
242 					GLint length;
243 					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
244 					if (length > 0)
245 					{
246 						std::vector<GLchar> source(length);
247 						glGetShaderSource(shaders[i], length, NULL, &source[0]);
248 						m_context.getTestContext().getLog()
249 							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
250 					}
251 					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
252 					if (length > 0)
253 					{
254 						std::vector<GLchar> log(length);
255 						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
256 						m_context.getTestContext().getLog()
257 							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
258 					}
259 				}
260 			}
261 			GLint length;
262 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
263 			if (length > 0)
264 			{
265 				std::vector<GLchar> log(length);
266 				glGetProgramInfoLog(program, length, NULL, &log[0]);
267 				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
268 			}
269 		}
270 
271 		return status == GL_TRUE ? true : false;
272 	}
273 
CreateProgram(const std::string & vs,const std::string & tcs,const std::string & tes,const std::string & gs,const std::string & fs)274 	GLuint CreateProgram(const std::string& vs, const std::string& tcs, const std::string& tes, const std::string& gs,
275 						 const std::string& fs)
276 	{
277 		const GLuint p = glCreateProgram();
278 		if (!vs.empty())
279 		{
280 			const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
281 			glAttachShader(p, sh);
282 			glDeleteShader(sh);
283 			const char* const src[2] = { kGLSLVer, vs.c_str() };
284 			glShaderSource(sh, 2, src, NULL);
285 			glCompileShader(sh);
286 		}
287 		if (!tcs.empty())
288 		{
289 			const GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
290 			glAttachShader(p, sh);
291 			glDeleteShader(sh);
292 			const char* const src[2] = { kGLSLVer, tcs.c_str() };
293 			glShaderSource(sh, 2, src, NULL);
294 			glCompileShader(sh);
295 		}
296 		if (!tes.empty())
297 		{
298 			const GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
299 			glAttachShader(p, sh);
300 			glDeleteShader(sh);
301 			const char* const src[2] = { kGLSLVer, tes.c_str() };
302 			glShaderSource(sh, 2, src, NULL);
303 			glCompileShader(sh);
304 		}
305 		if (!gs.empty())
306 		{
307 			const GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
308 			glAttachShader(p, sh);
309 			glDeleteShader(sh);
310 			const char* const src[2] = { kGLSLVer, gs.c_str() };
311 			glShaderSource(sh, 2, src, NULL);
312 			glCompileShader(sh);
313 		}
314 		if (!fs.empty())
315 		{
316 			const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
317 			glAttachShader(p, sh);
318 			glDeleteShader(sh);
319 			const char* const src[2] = { kGLSLVer, fs.c_str() };
320 			glShaderSource(sh, 2, src, NULL);
321 			glCompileShader(sh);
322 		}
323 		return p;
324 	}
325 
CreateProgram(const std::string & vs,const std::string & fs)326 	GLuint CreateProgram(const std::string& vs, const std::string& fs)
327 	{
328 		const GLuint p = glCreateProgram();
329 
330 		if (!vs.empty())
331 		{
332 			const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
333 			glAttachShader(p, sh);
334 			glDeleteShader(sh);
335 			const char* const src[2] = { kGLSLVer, vs.c_str() };
336 			glShaderSource(sh, 2, src, NULL);
337 			glCompileShader(sh);
338 		}
339 		if (!fs.empty())
340 		{
341 			const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
342 			glAttachShader(p, sh);
343 			glDeleteShader(sh);
344 			const char* const src[2] = { kGLSLVer, fs.c_str() };
345 			glShaderSource(sh, 2, src, NULL);
346 			glCompileShader(sh);
347 		}
348 
349 		return p;
350 	}
351 
CreateProgramCS(const std::string & cs)352 	GLuint CreateProgramCS(const std::string& cs)
353 	{
354 		const GLuint p = glCreateProgram();
355 
356 		if (!cs.empty())
357 		{
358 			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
359 			glAttachShader(p, sh);
360 			glDeleteShader(sh);
361 			const char* const src[2] = { kGLSLVer, cs.c_str() };
362 			glShaderSource(sh, 2, src, NULL);
363 			glCompileShader(sh);
364 		}
365 		return p;
366 	}
367 
BuildShaderProgram(GLenum type,const std::string & source)368 	GLuint BuildShaderProgram(GLenum type, const std::string& source)
369 	{
370 		if (type == GL_COMPUTE_SHADER)
371 		{
372 			const char* const src[3] = { kGLSLVer, "#extension GL_ARB_compute_shader : require\n", source.c_str() };
373 			return glCreateShaderProgramv(type, 3, src);
374 		}
375 
376 		const char* const src[2] = { kGLSLVer, source.c_str() };
377 		return glCreateShaderProgramv(type, 2, src);
378 	}
379 
ValidateReadBuffer(int x,int y,int w,int h,const vec3 & expected)380 	bool ValidateReadBuffer(int x, int y, int w, int h, const vec3& expected)
381 	{
382 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
383 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
384 		vec4					 g_color_eps  = vec4(
385 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
386 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
387 
388 		std::vector<vec3> display(w * h);
389 		glReadPixels(x, y, w, h, GL_RGB, GL_FLOAT, &display[0]);
390 
391 		bool result = true;
392 		for (int j = 0; j < h; ++j)
393 		{
394 			for (int i = 0; i < w; ++i)
395 			{
396 				if (!ColorEqual(display[j * w + i], expected, g_color_eps))
397 				{
398 					m_context.getTestContext().getLog()
399 						<< tcu::TestLog::Message << "Color at (" << x + i << ", " << y + j << ") is ("
400 						<< display[j * w + i][0] << " " << display[j * w + i][1] << " " << display[j * w + i][2]
401 						<< ") should be (" << expected[0] << " " << expected[1] << " " << expected[2] << ")."
402 						<< tcu::TestLog::EndMessage;
403 					result = false;
404 				}
405 			}
406 		}
407 
408 		return result;
409 	}
410 
ValidateWindow4Quads(const vec3 & lb,const vec3 & rb,const vec3 & rt,const vec3 & lt,int * bad_pixels=NULL)411 	bool ValidateWindow4Quads(const vec3& lb, const vec3& rb, const vec3& rt, const vec3& lt, int* bad_pixels = NULL)
412 	{
413 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
414 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
415 		vec4					 g_color_eps  = vec4(
416 			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
417 			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
418 
419 		const int		  width  = 100;
420 		const int		  height = 100;
421 		std::vector<vec3> fb(width * height);
422 		glReadPixels(0, 0, width, height, GL_RGB, GL_FLOAT, &fb[0]);
423 
424 		bool status = true;
425 		int  bad	= 0;
426 
427 		// left-bottom quad
428 		for (int y = 10; y < height / 2 - 10; ++y)
429 		{
430 			for (int x = 10; x < width / 2 - 10; ++x)
431 			{
432 				const int idx = y * width + x;
433 				if (!ColorEqual(fb[idx], lb, g_color_eps))
434 				{
435 					m_context.getTestContext().getLog()
436 						<< tcu::TestLog::Message << "First bad color (" << x << ", " << y << "): " << fb[idx][0] << " "
437 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
438 					status = false;
439 					bad++;
440 				}
441 			}
442 		}
443 		if (!status)
444 		{
445 			m_context.getTestContext().getLog()
446 				<< tcu::TestLog::Message << "Left-bottom quad checking failed. Bad pixels: " << bad
447 				<< tcu::TestLog::EndMessage;
448 			//return status;
449 		}
450 		// right-bottom quad
451 		for (int y = 10; y < height / 2 - 10; ++y)
452 		{
453 			for (int x = width / 2 + 10; x < width - 10; ++x)
454 			{
455 				const int idx = y * width + x;
456 				if (!ColorEqual(fb[idx], rb, g_color_eps))
457 				{
458 					m_context.getTestContext().getLog()
459 						<< tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
460 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
461 					status = false;
462 					bad++;
463 				}
464 			}
465 		}
466 		if (!status)
467 		{
468 			m_context.getTestContext().getLog()
469 				<< tcu::TestLog::Message << "right-bottom quad checking failed. Bad pixels: " << bad
470 				<< tcu::TestLog::EndMessage;
471 			//return status;
472 		}
473 		// right-top quad
474 		for (int y = height / 2 + 10; y < height - 10; ++y)
475 		{
476 			for (int x = width / 2 + 10; x < width - 10; ++x)
477 			{
478 				const int idx = y * width + x;
479 				if (!ColorEqual(fb[idx], rt, g_color_eps))
480 				{
481 					m_context.getTestContext().getLog()
482 						<< tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
483 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
484 					status = false;
485 					bad++;
486 				}
487 			}
488 		}
489 		if (!status)
490 		{
491 			m_context.getTestContext().getLog()
492 				<< tcu::TestLog::Message << "right-top quad checking failed. Bad pixels: " << bad
493 				<< tcu::TestLog::EndMessage;
494 			//return status;
495 		}
496 		// left-top quad
497 		for (int y = height / 2 + 10; y < height - 10; ++y)
498 		{
499 			for (int x = 10; x < width / 2 - 10; ++x)
500 			{
501 				const int idx = y * width + x;
502 				if (!ColorEqual(fb[idx], lt, g_color_eps))
503 				{
504 					m_context.getTestContext().getLog()
505 						<< tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
506 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
507 					status = false;
508 					bad++;
509 				}
510 			}
511 		}
512 		if (!status)
513 		{
514 			m_context.getTestContext().getLog()
515 				<< tcu::TestLog::Message << "left-top quad checking failed. Bad pixels: " << bad
516 				<< tcu::TestLog::EndMessage;
517 			//return status;
518 		}
519 		// middle horizontal line should be black
520 		for (int y = height / 2 - 2; y < height / 2 + 2; ++y)
521 		{
522 			for (int x = 0; x < width; ++x)
523 			{
524 				const int idx = y * width + x;
525 				if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
526 				{
527 					m_context.getTestContext().getLog()
528 						<< tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
529 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
530 					status = false;
531 					bad++;
532 				}
533 			}
534 		}
535 		if (!status)
536 		{
537 			m_context.getTestContext().getLog()
538 				<< tcu::TestLog::Message << "middle horizontal line checking failed. Bad pixels: " << bad
539 				<< tcu::TestLog::EndMessage;
540 			//return status;
541 		}
542 		// middle vertical line should be black
543 		for (int y = 0; y < height; ++y)
544 		{
545 			for (int x = width / 2 - 2; x < width / 2 + 2; ++x)
546 			{
547 				const int idx = y * width + x;
548 				if (!ColorEqual(fb[idx], vec3(0), g_color_eps))
549 				{
550 					m_context.getTestContext().getLog()
551 						<< tcu::TestLog::Message << "Bad color at (" << x << ", " << y << "): " << fb[idx][0] << " "
552 						<< fb[idx][1] << " " << fb[idx][2] << tcu::TestLog::EndMessage;
553 					status = false;
554 					bad++;
555 				}
556 			}
557 		}
558 		if (!status)
559 		{
560 			m_context.getTestContext().getLog()
561 				<< tcu::TestLog::Message << "middle vertical line checking failed. Bad pixels: " << bad
562 				<< tcu::TestLog::EndMessage;
563 			//return status;
564 		}
565 
566 		if (bad_pixels)
567 			*bad_pixels = bad;
568 		m_context.getTestContext().getLog()
569 			<< tcu::TestLog::Message << "Bad pixels: " << (bad_pixels == NULL ? 0 : *bad_pixels)
570 			<< ", counted bad: " << bad << tcu::TestLog::EndMessage;
571 		return status;
572 	}
573 
Translation(float tx,float ty,float tz)574 	const mat4 Translation(float tx, float ty, float tz)
575 	{
576 		float d[] = { 1.0f, 0.0f, 0.0f, tx, 0.0f, 1.0f, 0.0f, ty, 0.0f, 0.0f, 1.0f, tz, 0.0f, 0.0f, 0.0f, 1.0f };
577 		return mat4(d);
578 	}
579 
GLenumToString(GLenum e)580 	const char* GLenumToString(GLenum e)
581 	{
582 		switch (e)
583 		{
584 		case GL_SHADER_STORAGE_BUFFER_BINDING:
585 			return "GL_SHADER_STORAGE_BUFFER_BINDING";
586 		case GL_SHADER_STORAGE_BUFFER_START:
587 			return "GL_SHADER_STORAGE_BUFFER_START";
588 		case GL_SHADER_STORAGE_BUFFER_SIZE:
589 			return "GL_SHADER_STORAGE_BUFFER_SIZE";
590 		case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
591 			return "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS";
592 		case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS:
593 			return "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS";
594 		case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS:
595 			return "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS";
596 		case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS:
597 			return "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS";
598 		case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
599 			return "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS";
600 		case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
601 			return "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS";
602 		case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
603 			return "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS";
604 		case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
605 			return "GL_MAX_SHADER_STORAGE_BLOCK_SIZE";
606 		case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
607 			return "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS";
608 		case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
609 			return "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES";
610 		case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
611 			return "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT";
612 
613 		default:
614 			assert(0);
615 			break;
616 		}
617 		return NULL;
618 	}
619 };
620 
621 //-----------------------------------------------------------------------------
622 // 1.1 BasicBasic
623 //-----------------------------------------------------------------------------
624 
625 class BasicBasic : public ShaderStorageBufferObjectBase
626 {
627 	GLuint m_program;
628 	GLuint m_buffer;
629 	GLuint m_vertex_array;
630 
RunIteration(GLuint index)631 	bool RunIteration(GLuint index)
632 	{
633 		glClear(GL_COLOR_BUFFER_BIT);
634 		glShaderStorageBlockBinding(m_program, 0, index);
635 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, m_buffer);
636 		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
637 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, 0);
638 
639 		return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
640 	}
641 
Setup()642 	virtual long Setup()
643 	{
644 		m_program	  = 0;
645 		m_buffer	   = 0;
646 		m_vertex_array = 0;
647 		return NO_ERROR;
648 	}
649 
Run()650 	virtual long Run()
651 	{
652 		if (!SupportedInVS(1))
653 			return NOT_SUPPORTED;
654 
655 		const char* const glsl_vs =
656 			NL "layout(std430, binding = 1) buffer InputBuffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL
657 			   "void main() {" NL "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}";
658 
659 		const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
660 									   "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
661 
662 		m_program = CreateProgram(glsl_vs, glsl_fs);
663 		glLinkProgram(m_program);
664 		if (!CheckProgram(m_program))
665 			return ERROR;
666 
667 		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 };
668 		glGenBuffers(1, &m_buffer);
669 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
670 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
671 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
672 
673 		glGenVertexArrays(1, &m_vertex_array);
674 		glBindVertexArray(m_vertex_array);
675 
676 		glUseProgram(m_program);
677 
678 		for (GLuint i = 0; i < 8; ++i)
679 		{
680 			if (!RunIteration(i))
681 				return ERROR;
682 		}
683 		return NO_ERROR;
684 	}
685 
Cleanup()686 	virtual long Cleanup()
687 	{
688 		glUseProgram(0);
689 		glDeleteProgram(m_program);
690 		glDeleteBuffers(1, &m_buffer);
691 		glDeleteVertexArrays(1, &m_vertex_array);
692 		return NO_ERROR;
693 	}
694 };
695 
696 class BasicBasicCS : public ShaderStorageBufferObjectBase
697 {
698 	GLuint m_program;
699 	GLuint m_buffer;
700 
Setup()701 	virtual long Setup()
702 	{
703 		m_program = 0;
704 		m_buffer  = 0;
705 		return NO_ERROR;
706 	}
707 
Run()708 	virtual long Run()
709 	{
710 		const char* const glsl_cs = NL "layout(local_size_x = 1) in;" NL "buffer Buffer {" NL "  int result;" NL "};" NL
711 									   "void main() {" NL "  result = 7;" NL "}";
712 		m_program = CreateProgramCS(glsl_cs);
713 		glLinkProgram(m_program);
714 		if (!CheckProgram(m_program))
715 			return ERROR;
716 
717 		glGenBuffers(1, &m_buffer);
718 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
719 		glBufferData(GL_SHADER_STORAGE_BUFFER, 4, 0, GL_STATIC_READ);
720 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
721 
722 		glUseProgram(m_program);
723 		glDispatchCompute(1, 1, 1);
724 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
725 
726 		GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
727 		if (!out_data)
728 			return ERROR;
729 		if (*out_data == 7)
730 			return NO_ERROR;
731 		else
732 			return ERROR;
733 	}
734 
Cleanup()735 	virtual long Cleanup()
736 	{
737 		glUseProgram(0);
738 		glDeleteProgram(m_program);
739 		glDeleteBuffers(1, &m_buffer);
740 		return NO_ERROR;
741 	}
742 };
743 //-----------------------------------------------------------------------------
744 // 1.2 BasicMax
745 //-----------------------------------------------------------------------------
746 
747 class BasicMax : public ShaderStorageBufferObjectBase
748 {
Check(GLenum e,GLint64 value,bool max_value)749 	bool Check(GLenum e, GLint64 value, bool max_value)
750 	{
751 		GLint	 i;
752 		GLint64   i64;
753 		GLfloat   f;
754 		GLdouble  d;
755 		GLboolean b;
756 
757 		glGetIntegerv(e, &i);
758 		glGetInteger64v(e, &i64);
759 		glGetFloatv(e, &f);
760 		glGetDoublev(e, &d);
761 		glGetBooleanv(e, &b);
762 
763 		bool status = true;
764 		if (max_value)
765 		{
766 			if (static_cast<GLint64>(i) < value)
767 				status = false;
768 			if (i64 < value)
769 				status = false;
770 			if (static_cast<GLint64>(f) < value)
771 				status = false;
772 			if (static_cast<GLint64>(d) < value)
773 				status = false;
774 
775 			if (!status)
776 			{
777 				m_context.getTestContext().getLog()
778 					<< tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at least "
779 					<< static_cast<GLint>(value) << tcu::TestLog::EndMessage;
780 			}
781 		}
782 		else
783 		{
784 			if (static_cast<GLint64>(i) > value)
785 				status = false;
786 			if (i64 > value)
787 				status = false;
788 			if (static_cast<GLint64>(f) > value)
789 				status = false;
790 			if (static_cast<GLint64>(d) > value)
791 				status = false;
792 
793 			if (!status)
794 			{
795 				m_context.getTestContext().getLog()
796 					<< tcu::TestLog::Message << GLenumToString(e) << " is " << i << " should be at most "
797 					<< static_cast<GLint>(value) << tcu::TestLog::EndMessage;
798 			}
799 		}
800 		return status;
801 	}
802 
Run()803 	virtual long Run()
804 	{
805 		if (!Check(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, 0, true))
806 			return ERROR;
807 		if (!Check(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, 0, true))
808 			return ERROR;
809 		if (!Check(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, 0, true))
810 			return ERROR;
811 		if (!Check(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, 0, true))
812 			return ERROR;
813 		if (!Check(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, 8, true))
814 			return ERROR;
815 		if (!Check(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, 8, true))
816 			return ERROR;
817 		if (!Check(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, 8, true))
818 			return ERROR;
819 		if (!Check(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, 16777216 /* 2^24 */, true))
820 			return ERROR;
821 		if (!Check(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, 8, true))
822 			return ERROR;
823 		if (!Check(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8, true))
824 			return ERROR;
825 		if (!Check(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, 256, false))
826 			return ERROR;
827 		return NO_ERROR;
828 	}
829 };
830 //-----------------------------------------------------------------------------
831 // 1.3 BasicBinding
832 //-----------------------------------------------------------------------------
833 
834 class BasicBinding : public ShaderStorageBufferObjectBase
835 {
836 	GLuint m_buffer[4];
837 
Check(GLenum e,GLuint expected)838 	bool Check(GLenum e, GLuint expected)
839 	{
840 		GLint	 i;
841 		GLint64   i64;
842 		GLfloat   f;
843 		GLdouble  d;
844 		GLboolean b;
845 
846 		glGetIntegerv(e, &i);
847 		glGetInteger64v(e, &i64);
848 		glGetFloatv(e, &f);
849 		glGetDoublev(e, &d);
850 		glGetBooleanv(e, &b);
851 
852 		bool status = true;
853 		if (static_cast<GLuint>(i) != expected)
854 			status = false;
855 		if (static_cast<GLuint>(i64) != expected)
856 			status = false;
857 		if (static_cast<GLuint>(f) != expected)
858 			status = false;
859 		if (static_cast<GLuint>(d) != expected)
860 			status = false;
861 		if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
862 			status = false;
863 
864 		if (!status)
865 		{
866 			m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " is " << i
867 												<< " should be " << expected << tcu::TestLog::EndMessage;
868 		}
869 		return status;
870 	}
871 
CheckIndexed(GLenum e,GLuint index,GLuint expected)872 	bool CheckIndexed(GLenum e, GLuint index, GLuint expected)
873 	{
874 		GLint	 i;
875 		GLint64   i64;
876 		GLfloat   f;
877 		GLdouble  d;
878 		GLboolean b;
879 
880 		glGetIntegeri_v(e, index, &i);
881 		glGetInteger64i_v(e, index, &i64);
882 		glGetFloati_v(e, index, &f);
883 		glGetDoublei_v(e, index, &d);
884 		glGetBooleani_v(e, index, &b);
885 
886 		bool status = true;
887 		if (static_cast<GLuint>(i) != expected)
888 			status = false;
889 		if (static_cast<GLuint>(i64) != expected)
890 			status = false;
891 		if (static_cast<GLuint>(f) != expected)
892 			status = false;
893 		if (static_cast<GLuint>(d) != expected)
894 			status = false;
895 		if (b != (expected != 0 ? GL_TRUE : GL_FALSE))
896 			status = false;
897 
898 		if (!status)
899 		{
900 			m_context.getTestContext().getLog() << tcu::TestLog::Message << GLenumToString(e) << " at index " << index
901 												<< " is " << i << " should be " << expected << tcu::TestLog::EndMessage;
902 		}
903 		return status;
904 	}
905 
Setup()906 	virtual long Setup()
907 	{
908 		memset(m_buffer, 0, sizeof(m_buffer));
909 		return NO_ERROR;
910 	}
911 
Run()912 	virtual long Run()
913 	{
914 		// check default state
915 		if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
916 			return ERROR;
917 		for (GLuint i = 0; i < 8; ++i)
918 		{
919 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
920 				return ERROR;
921 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
922 				return ERROR;
923 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
924 				return ERROR;
925 		}
926 
927 		glGenBuffers(4, m_buffer);
928 		for (GLuint i = 0; i < 8; ++i)
929 		{
930 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0]);
931 
932 			if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
933 				return ERROR;
934 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
935 				return ERROR;
936 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
937 				return ERROR;
938 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
939 				return ERROR;
940 
941 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, 0);
942 
943 			if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
944 				return ERROR;
945 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
946 				return ERROR;
947 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
948 				return ERROR;
949 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
950 				return ERROR;
951 		}
952 
953 		for (GLuint i = 0; i < 8; ++i)
954 		{
955 			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_buffer[0], 256, 512);
956 
957 			if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[0]))
958 				return ERROR;
959 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, m_buffer[0]))
960 				return ERROR;
961 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 256))
962 				return ERROR;
963 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 512))
964 				return ERROR;
965 
966 			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 512, 128);
967 
968 			if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
969 				return ERROR;
970 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
971 				return ERROR;
972 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
973 				return ERROR;
974 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
975 				return ERROR;
976 
977 			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, 0, 0, 0);
978 
979 			if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
980 				return ERROR;
981 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
982 				return ERROR;
983 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, i, 0))
984 				return ERROR;
985 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, i, 0))
986 				return ERROR;
987 		}
988 
989 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[2]);
990 		if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[2]))
991 			return ERROR;
992 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 0, m_buffer[2]))
993 			return ERROR;
994 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 0, 0))
995 			return ERROR;
996 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 0, 0))
997 			return ERROR;
998 
999 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_buffer[3]);
1000 		if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[3]))
1001 			return ERROR;
1002 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 5, m_buffer[3]))
1003 			return ERROR;
1004 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 5, 0))
1005 			return ERROR;
1006 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 5, 0))
1007 			return ERROR;
1008 
1009 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_buffer[1], 2048, 1000);
1010 		if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, m_buffer[1]))
1011 			return ERROR;
1012 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, 7, m_buffer[1]))
1013 			return ERROR;
1014 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_START, 7, 2048))
1015 			return ERROR;
1016 		if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_SIZE, 7, 1000))
1017 			return ERROR;
1018 
1019 		glDeleteBuffers(4, m_buffer);
1020 		memset(m_buffer, 0, sizeof(m_buffer));
1021 
1022 		if (!Check(GL_SHADER_STORAGE_BUFFER_BINDING, 0))
1023 			return ERROR;
1024 		for (GLuint i = 0; i < 8; ++i)
1025 		{
1026 			if (!CheckIndexed(GL_SHADER_STORAGE_BUFFER_BINDING, i, 0))
1027 				return ERROR;
1028 		}
1029 
1030 		return NO_ERROR;
1031 	}
1032 
Cleanup()1033 	virtual long Cleanup()
1034 	{
1035 		glDeleteBuffers(4, m_buffer);
1036 		return NO_ERROR;
1037 	}
1038 };
1039 //-----------------------------------------------------------------------------
1040 // 1.4 BasicSyntax
1041 //-----------------------------------------------------------------------------
1042 
1043 class BasicSyntax : public ShaderStorageBufferObjectBase
1044 {
1045 	GLuint m_program;
1046 	GLuint m_buffer;
1047 	GLuint m_vertex_array;
1048 
RunIteration(const char * vs,const char * fs)1049 	bool RunIteration(const char* vs, const char* fs)
1050 	{
1051 		if (m_program != 0)
1052 			glDeleteProgram(m_program);
1053 		m_program = CreateProgram(vs, fs);
1054 		glLinkProgram(m_program);
1055 		if (!CheckProgram(m_program))
1056 			return false;
1057 
1058 		glClear(GL_COLOR_BUFFER_BIT);
1059 		glUseProgram(m_program);
1060 		glDrawArrays(GL_TRIANGLES, 0, 3);
1061 
1062 		return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1063 	}
1064 
Setup()1065 	virtual long Setup()
1066 	{
1067 		m_program	  = 0;
1068 		m_buffer	   = 0;
1069 		m_vertex_array = 0;
1070 		return NO_ERROR;
1071 	}
1072 
Run()1073 	virtual long Run()
1074 	{
1075 		if (!SupportedInVS(1))
1076 			return NOT_SUPPORTED;
1077 
1078 		const int		  kCount		  = 8;
1079 		const char* const glsl_vs[kCount] = {
1080 			NL "layout(std430) buffer Buffer {" NL "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1081 			   "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1082 			NL "coherent buffer Buffer {" NL "  buffer vec4 position0;" NL "  coherent vec4 position1;" NL
1083 			   "  restrict readonly vec4 position2;" NL "} g_input_buffer;" NL "void main() {" NL
1084 			   "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1085 			   "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1086 			   "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1087 			NL "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
1088 			   "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
1089 			NL "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1090 			   "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1091 			   "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1092 			   "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1093 			NL "buffer Buffer {" NL "  vec4 position[3];" NL "} g_buffer[1];" NL "void main() {" NL
1094 			   "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1095 			NL "layout(shared) coherent buffer Buffer {" NL "  restrict volatile vec4 position0;" NL
1096 			   "  buffer readonly vec4 position1;" NL "  vec4 position2;" NL "} g_buffer[1];" NL "void main() {" NL
1097 			   "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1098 			   "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1099 			   "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1100 			NL "layout(packed) coherent buffer Buffer {" NL "  vec4 position01[];" NL "  vec4 position2;" NL
1101 			   "} g_buffer;" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1102 			   "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1103 			   "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1104 			NL "layout(std430) coherent buffer Buffer {" NL "  coherent vec4 position01[];" NL "  vec4 position2[];" NL
1105 			   "} g_buffer;" NL "void main() {" NL "  switch (gl_VertexID) {" NL
1106 			   "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
1107 			   "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
1108 			   "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
1109 		};
1110 		const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1111 									   "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1112 
1113 		// full viewport triangle
1114 		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 };
1115 		glGenBuffers(1, &m_buffer);
1116 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1117 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1118 
1119 		glGenVertexArrays(1, &m_vertex_array);
1120 		glBindVertexArray(m_vertex_array);
1121 
1122 		for (int i = 0; i < kCount; ++i)
1123 		{
1124 			if (!RunIteration(glsl_vs[i], glsl_fs))
1125 				return ERROR;
1126 		}
1127 
1128 		return NO_ERROR;
1129 	}
1130 
Cleanup()1131 	virtual long Cleanup()
1132 	{
1133 		glUseProgram(0);
1134 		glDeleteProgram(m_program);
1135 		glDeleteBuffers(1, &m_buffer);
1136 		glDeleteVertexArrays(1, &m_vertex_array);
1137 		return NO_ERROR;
1138 	}
1139 };
1140 //-----------------------------------------------------------------------------
1141 // 1.5 BasicSyntaxSSO
1142 //-----------------------------------------------------------------------------
1143 
1144 class BasicSyntaxSSO : public ShaderStorageBufferObjectBase
1145 {
1146 	GLuint m_pipeline;
1147 	GLuint m_vsp, m_fsp;
1148 	GLuint m_buffer;
1149 	GLuint m_vertex_array;
1150 
RunIteration(const char * vs)1151 	bool RunIteration(const char* vs)
1152 	{
1153 		if (m_vsp != 0)
1154 			glDeleteProgram(m_vsp);
1155 		m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, vs);
1156 		if (!CheckProgram(m_vsp))
1157 			return false;
1158 
1159 		glClear(GL_COLOR_BUFFER_BIT);
1160 		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
1161 		glDrawArrays(GL_TRIANGLES, 0, 3);
1162 
1163 		return ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0));
1164 	}
1165 
Setup()1166 	virtual long Setup()
1167 	{
1168 		m_pipeline = 0;
1169 		m_vsp = m_fsp  = 0;
1170 		m_buffer	   = 0;
1171 		m_vertex_array = 0;
1172 		return NO_ERROR;
1173 	}
1174 
Run()1175 	virtual long Run()
1176 	{
1177 		if (!SupportedInVS(1))
1178 			return NOT_SUPPORTED;
1179 		const int		  kCount		  = 8;
1180 		const char* const glsl_vs[kCount] = {
1181 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std430) buffer Buffer {" NL
1182 			   "  vec4 position[3];" NL "} g_input_buffer;" NL "void main() {" NL
1183 			   "  gl_Position = g_input_buffer.position[gl_VertexID];" NL "}",
1184 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "coherent buffer Buffer {" NL
1185 			   "  vec4 position0;" NL "  coherent vec4 position1;" NL "  restrict readonly vec4 position2;" NL
1186 			   "} g_input_buffer;" NL "void main() {" NL
1187 			   "  if (gl_VertexID == 0) gl_Position = g_input_buffer.position0;" NL
1188 			   "  if (gl_VertexID == 1) gl_Position = g_input_buffer.position1;" NL
1189 			   "  if (gl_VertexID == 2) gl_Position = g_input_buffer.position2;" NL "}",
1190 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL
1191 			   "layout(std140, binding = 0) readonly buffer Buffer {" NL "  readonly vec4 position[];" NL "};" NL
1192 			   "void main() {" NL "  gl_Position = position[gl_VertexID];" NL "}",
1193 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL
1194 			   "layout(std430, column_major, std140, std430, row_major, packed, shared) buffer;" NL
1195 			   "layout(std430) buffer;" NL "coherent restrict volatile buffer Buffer {" NL
1196 			   "  restrict coherent vec4 position[];" NL "} g_buffer;" NL "void main() {" NL
1197 			   "  gl_Position = g_buffer.position[gl_VertexID];" NL "}",
1198 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "buffer Buffer {" NL "  vec4 position[3];" NL
1199 			   "} g_buffer[1];" NL "void main() {" NL "  gl_Position = g_buffer[0].position[gl_VertexID];" NL "}",
1200 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(shared) coherent buffer Buffer {" NL
1201 			   "  restrict volatile vec4 position0;" NL "  readonly vec4 position1;" NL "  vec4 position2;" NL
1202 			   "} g_buffer[1];" NL "void main() {" NL "  if (gl_VertexID == 0) gl_Position = g_buffer[0].position0;" NL
1203 			   "  else if (gl_VertexID == 1) gl_Position = g_buffer[0].position1;" NL
1204 			   "  else if (gl_VertexID == 2) gl_Position = g_buffer[0].position2;" NL "}",
1205 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(packed) coherent buffer Buffer {" NL
1206 			   "  vec4 position01[];" NL "  vec4 position2;" NL "} g_buffer;" NL "void main() {" NL
1207 			   "  if (gl_VertexID == 0) gl_Position = g_buffer.position01[0];" NL
1208 			   "  else if (gl_VertexID == 1) gl_Position = g_buffer.position01[1];" NL
1209 			   "  else if (gl_VertexID == 2) gl_Position = g_buffer.position2;" NL "}",
1210 			NL "out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL
1211 			   "  coherent vec4 position01[];" NL "  vec4 position2[];" NL "} g_buffer;" NL "void main() {" NL
1212 			   "  switch (gl_VertexID) {" NL "    case 0: gl_Position = g_buffer.position01[0]; break;" NL
1213 			   "    case 1: gl_Position = g_buffer.position01[1]; break;" NL
1214 			   "    case 2: gl_Position = g_buffer.position2[gl_VertexID - 2]; break;" NL "  }" NL "}",
1215 		};
1216 		const char* const glsl_fs = NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
1217 									   "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1218 		m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
1219 		if (!CheckProgram(m_fsp))
1220 			return ERROR;
1221 
1222 		glGenProgramPipelines(1, &m_pipeline);
1223 		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
1224 
1225 		// full viewport triangle
1226 		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 };
1227 		glGenBuffers(1, &m_buffer);
1228 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1229 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
1230 
1231 		glBindProgramPipeline(m_pipeline);
1232 
1233 		glGenVertexArrays(1, &m_vertex_array);
1234 		glBindVertexArray(m_vertex_array);
1235 
1236 		for (int i = 0; i < kCount; ++i)
1237 		{
1238 			if (!RunIteration(glsl_vs[i]))
1239 				return ERROR;
1240 		}
1241 
1242 		return NO_ERROR;
1243 	}
1244 
Cleanup()1245 	virtual long Cleanup()
1246 	{
1247 		glDeleteProgramPipelines(1, &m_pipeline);
1248 		glDeleteProgram(m_vsp);
1249 		glDeleteProgram(m_fsp);
1250 		glDeleteBuffers(1, &m_buffer);
1251 		glDeleteVertexArrays(1, &m_vertex_array);
1252 		return NO_ERROR;
1253 	}
1254 };
1255 //-----------------------------------------------------------------------------
1256 // 1.6.x BasicStdLayoutBase
1257 //-----------------------------------------------------------------------------
1258 
1259 class BasicStdLayoutBaseVS : public ShaderStorageBufferObjectBase
1260 {
1261 	GLuint m_program;
1262 	GLuint m_buffer[2];
1263 	GLuint m_vertex_array;
1264 
1265 	virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1266 
Setup()1267 	virtual long Setup()
1268 	{
1269 		m_program = 0;
1270 		memset(m_buffer, 0, sizeof(m_buffer));
1271 		m_vertex_array = 0;
1272 		return NO_ERROR;
1273 	}
1274 
Run()1275 	virtual long Run()
1276 	{
1277 		if (!SupportedInVS(2))
1278 			return NOT_SUPPORTED;
1279 		std::vector<GLubyte> in_data;
1280 		const char*			 glsl_vs = GetInput(in_data);
1281 
1282 		m_program = CreateProgram(glsl_vs, "");
1283 		glLinkProgram(m_program);
1284 		if (!CheckProgram(m_program))
1285 			return ERROR;
1286 
1287 		glGenBuffers(2, m_buffer);
1288 
1289 		// output buffer
1290 		std::vector<GLubyte> out_data(in_data.size());
1291 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1292 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &out_data[0], GL_STATIC_DRAW);
1293 
1294 		// input buffer
1295 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1296 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1297 
1298 		glGenVertexArrays(1, &m_vertex_array);
1299 		glEnable(GL_RASTERIZER_DISCARD);
1300 
1301 		glUseProgram(m_program);
1302 		glBindVertexArray(m_vertex_array);
1303 		glDrawArrays(GL_POINTS, 0, 1);
1304 
1305 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
1306 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1307 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), &out_data[0]);
1308 
1309 		bool status = true;
1310 		for (size_t i = 0; i < in_data.size(); ++i)
1311 		{
1312 			if (in_data[i] != out_data[i])
1313 			{
1314 				m_context.getTestContext().getLog()
1315 					<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1316 					<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1317 				status = false;
1318 			}
1319 		}
1320 		if (!status)
1321 			return ERROR;
1322 		return NO_ERROR;
1323 	}
1324 
Cleanup()1325 	virtual long Cleanup()
1326 	{
1327 		glDisable(GL_RASTERIZER_DISCARD);
1328 		glUseProgram(0);
1329 		glDeleteProgram(m_program);
1330 		glDeleteBuffers(2, m_buffer);
1331 		glDeleteVertexArrays(1, &m_vertex_array);
1332 		return NO_ERROR;
1333 	}
1334 };
1335 
1336 class BasicStdLayoutBaseCS : public ShaderStorageBufferObjectBase
1337 {
1338 	GLuint m_program;
1339 	GLuint m_buffer[2];
1340 
1341 	virtual const char* GetInput(std::vector<GLubyte>& in_data) = 0;
1342 
Setup()1343 	virtual long Setup()
1344 	{
1345 		m_program = 0;
1346 		memset(m_buffer, 0, sizeof(m_buffer));
1347 		return NO_ERROR;
1348 	}
1349 
Run()1350 	virtual long Run()
1351 	{
1352 		std::vector<GLubyte> in_data;
1353 		std::stringstream	ss;
1354 		ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
1355 
1356 		m_program = CreateProgramCS(ss.str());
1357 		glLinkProgram(m_program);
1358 		if (!CheckProgram(m_program))
1359 			return ERROR;
1360 
1361 		glGenBuffers(2, m_buffer);
1362 
1363 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
1364 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
1365 		std::vector<GLubyte> out_d(in_data.size());
1366 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
1367 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)out_d.size(), &out_d[0], GL_STATIC_DRAW);
1368 
1369 		glUseProgram(m_program);
1370 		glDispatchCompute(1, 1, 1);
1371 
1372 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1373 		GLubyte* out_data =
1374 			(GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data.size(), GL_MAP_READ_BIT);
1375 		if (!out_data)
1376 			return ERROR;
1377 
1378 		bool status = true;
1379 
1380 		for (size_t i = 0; i < in_data.size(); ++i)
1381 		{
1382 			if (in_data[i] != out_data[i])
1383 			{
1384 				m_context.getTestContext().getLog()
1385 					<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
1386 					<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[i]) << tcu::TestLog::EndMessage;
1387 				status = false;
1388 			}
1389 		}
1390 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1391 		if (!status)
1392 			return ERROR;
1393 		return NO_ERROR;
1394 	}
1395 
Cleanup()1396 	virtual long Cleanup()
1397 	{
1398 		glUseProgram(0);
1399 		glDeleteProgram(m_program);
1400 		glDeleteBuffers(2, m_buffer);
1401 		return NO_ERROR;
1402 	}
1403 };
1404 //-----------------------------------------------------------------------------
1405 // 1.6.1 BasicStd430LayoutCase1
1406 //-----------------------------------------------------------------------------
GetInput430c1(std::vector<GLubyte> & in_data)1407 const char* GetInput430c1(std::vector<GLubyte>& in_data)
1408 {
1409 	in_data.resize(6 * 4);
1410 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1411 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1412 	fp[0]	 = 1.0f;
1413 	fp[1]	 = 2.0f;
1414 	fp[2]	 = 3.0f;
1415 	fp[3]	 = 4.0f;
1416 	ip[4]	 = 5;
1417 	ip[5]	 = 6;
1418 
1419 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1420 			  "  ivec2 data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL
1421 			  "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1422 			  "  g_output.data0 = g_input.data0;" NL
1423 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1424 			  "  g_output.data2 = g_input.data2;" NL "}";
1425 }
1426 
1427 class BasicStd430LayoutCase1VS : public BasicStdLayoutBaseVS
1428 {
GetInput(std::vector<GLubyte> & in_data)1429 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1430 	{
1431 		return GetInput430c1(in_data);
1432 	}
1433 };
1434 
1435 class BasicStd430LayoutCase1CS : public BasicStdLayoutBaseCS
1436 {
GetInput(std::vector<GLubyte> & in_data)1437 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1438 	{
1439 		return GetInput430c1(in_data);
1440 	}
1441 };
1442 //-----------------------------------------------------------------------------
1443 // 1.6.2 BasicStd430LayoutCase2
1444 //-----------------------------------------------------------------------------
GetInput430c2(std::vector<GLubyte> & in_data)1445 const char* GetInput430c2(std::vector<GLubyte>& in_data)
1446 {
1447 	in_data.resize(20 * 4);
1448 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1449 	fp[0]	 = 1.0f;
1450 	fp[1]	 = 2.0f;
1451 	fp[2]	 = 3.0f;
1452 	fp[3]	 = 4.0f;
1453 	fp[4]	 = 5.0f;
1454 	fp[5]	 = 6.0f;
1455 	fp[8]	 = 7.0f;
1456 	fp[9]	 = 8.0f;
1457 	fp[10]	= 9.0f;
1458 	fp[12]	= 10.0f;
1459 	fp[13]	= 11.0f;
1460 	fp[14]	= 12.0f;
1461 	fp[16]	= 13.0f;
1462 
1463 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1464 			  "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1465 			  "layout(std430, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1466 			  "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1467 			  "  g_output.data0 = g_input.data0;" NL
1468 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1469 			  "  g_output.data2 = g_input.data2;" NL
1470 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1471 			  "  g_output.data4 = g_input.data4;" NL "}";
1472 }
1473 
1474 class BasicStd430LayoutCase2VS : public BasicStdLayoutBaseVS
1475 {
GetInput(std::vector<GLubyte> & in_data)1476 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1477 	{
1478 		return GetInput430c2(in_data);
1479 	}
1480 };
1481 
1482 class BasicStd430LayoutCase2CS : public BasicStdLayoutBaseCS
1483 {
GetInput(std::vector<GLubyte> & in_data)1484 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1485 	{
1486 		return GetInput430c2(in_data);
1487 	}
1488 };
1489 
1490 //-----------------------------------------------------------------------------
1491 // 1.6.3 BasicStd430LayoutCase3
1492 //-----------------------------------------------------------------------------
GetInput430c3(std::vector<GLubyte> & in_data)1493 const char* GetInput430c3(std::vector<GLubyte>& in_data)
1494 {
1495 	in_data.resize(16 * 4);
1496 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1497 	fp[0]	 = 1.0f;
1498 	fp[1]	 = 2.0f;
1499 	fp[2]	 = 3.0f;
1500 	fp[3]	 = 0.0f;
1501 	fp[4]	 = 4.0f;
1502 	fp[5]	 = 5.0f;
1503 	fp[6]	 = 6.0f;
1504 	fp[7]	 = 0.0f;
1505 	fp[8]	 = 7.0f;
1506 	fp[9]	 = 8.0f;
1507 	fp[10]	= 9.0f;
1508 	fp[11]	= 10.0f;
1509 	fp[12]	= 11.0f;
1510 	fp[13]	= 12.0f;
1511 	fp[14]	= 13.0f;
1512 	fp[15]	= 14.0f;
1513 
1514 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat2x3 data0;" NL
1515 			  "  layout(row_major) mat4x2 data1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
1516 			  "  layout(column_major) mat2x3 data0;" NL "  layout(row_major) mat4x2 data1;" NL "} g_output;" NL
1517 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL "}";
1518 }
1519 
1520 class BasicStd430LayoutCase3VS : public BasicStdLayoutBaseVS
1521 {
GetInput(std::vector<GLubyte> & in_data)1522 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1523 	{
1524 		return GetInput430c3(in_data);
1525 	}
1526 };
1527 
1528 class BasicStd430LayoutCase3CS : public BasicStdLayoutBaseCS
1529 {
GetInput(std::vector<GLubyte> & in_data)1530 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1531 	{
1532 		return GetInput430c3(in_data);
1533 	}
1534 };
1535 
1536 //-----------------------------------------------------------------------------
1537 // 1.6.4 BasicStd430LayoutCase4
1538 //-----------------------------------------------------------------------------
GetInput430c4(std::vector<GLubyte> & in_data)1539 const char* GetInput430c4(std::vector<GLubyte>& in_data)
1540 {
1541 	in_data.resize(20 * 4);
1542 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1543 	fp[0]	 = 1.0f;
1544 	fp[1]	 = 2.0f;
1545 	fp[2]	 = 3.0f;
1546 	fp[3]	 = 4.0f;
1547 	fp[4]	 = 5.0f;
1548 	fp[5]	 = 6.0f;
1549 	fp[6]	 = 7.0f;
1550 	fp[7]	 = 8.0f;
1551 	fp[8]	 = 9.0f;
1552 	fp[9]	 = 10.0f;
1553 	fp[10]	= 11.0f;
1554 	fp[12]	= 12.0f;
1555 	fp[13]	= 13.0f;
1556 	fp[14]	= 14.0f;
1557 	fp[16]	= 15.0f;
1558 
1559 	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
1560 			  "  float data2;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
1561 			  "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
1562 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1563 			  "  g_output.data2 = g_input.data2;" NL "}";
1564 }
1565 
1566 class BasicStd430LayoutCase4VS : public BasicStdLayoutBaseVS
1567 {
GetInput(std::vector<GLubyte> & in_data)1568 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1569 	{
1570 		return GetInput430c4(in_data);
1571 	}
1572 };
1573 
1574 class BasicStd430LayoutCase4CS : public BasicStdLayoutBaseCS
1575 {
GetInput(std::vector<GLubyte> & in_data)1576 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1577 	{
1578 		return GetInput430c4(in_data);
1579 	}
1580 };
1581 
1582 //-----------------------------------------------------------------------------
1583 // 1.6.5 BasicStd430LayoutCase5
1584 //-----------------------------------------------------------------------------
GetInput430c5(std::vector<GLubyte> & in_data)1585 const char* GetInput430c5(std::vector<GLubyte>& in_data)
1586 {
1587 	in_data.resize(8 * 4);
1588 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1589 	fp[0]	 = 1.0f;
1590 	fp[1]	 = 3.0f;
1591 	fp[2]	 = 5.0f;
1592 	fp[3]	 = 7.0f;
1593 	fp[4]	 = 2.0f;
1594 	fp[5]	 = 4.0f;
1595 	fp[6]	 = 6.0f;
1596 	fp[7]	 = 8.0f;
1597 
1598 	return NL "layout(std430, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
1599 			  "layout(std430, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
1600 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
1601 }
1602 
1603 class BasicStd430LayoutCase5VS : public BasicStdLayoutBaseVS
1604 {
GetInput(std::vector<GLubyte> & in_data)1605 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1606 	{
1607 		return GetInput430c5(in_data);
1608 	}
1609 };
1610 
1611 class BasicStd430LayoutCase5CS : public BasicStdLayoutBaseCS
1612 {
GetInput(std::vector<GLubyte> & in_data)1613 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1614 	{
1615 		return GetInput430c5(in_data);
1616 	}
1617 };
1618 
1619 //-----------------------------------------------------------------------------
1620 // 1.6.6 BasicStd430LayoutCase6
1621 //-----------------------------------------------------------------------------
GetInput430c6(std::vector<GLubyte> & in_data)1622 const char* GetInput430c6(std::vector<GLubyte>& in_data)
1623 {
1624 	in_data.resize(92 * 4);
1625 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1626 	fp[0]	 = 1.0f;
1627 	fp[1]	 = 2.0f;
1628 	fp[2]	 = 3.0f;
1629 	fp[3]	 = 4.0f;
1630 	fp[4]	 = 5.0f;
1631 	fp[5]	 = 0.0f;
1632 	fp[6]	 = 6.0f;
1633 	fp[7]	 = 7.0f;
1634 	fp[8]	 = 8.0f;
1635 	fp[9]	 = 9.0f;
1636 	fp[10]	= 10.0f;
1637 	fp[11]	= 11.0f;
1638 	fp[12]	= 12.0f;
1639 	fp[13]	= 0.0f;
1640 	fp[14]	= 0.0f;
1641 	fp[15]	= 0.0f;
1642 	fp[16]	= 13.0f;
1643 	fp[17]	= 14.0f;
1644 	fp[18]	= 15.0f;
1645 	fp[19]	= 0.0f;
1646 	fp[20]	= 16.0f;
1647 	fp[21]	= 17.0f;
1648 	fp[22]	= 18.0f;
1649 	fp[23]	= 0.0f;
1650 	fp[24]	= 19.0f;
1651 	fp[25]	= 20.0f;
1652 	fp[26]	= 21.0f;
1653 	fp[27]	= 22.0f;
1654 	fp[28]	= 23.0f;
1655 	fp[29]	= 24.0f;
1656 	fp[30]	= 25.0f;
1657 	fp[31]	= 26.0f;
1658 	fp[32]	= 27.0f;
1659 	fp[33]	= 28.0f;
1660 	fp[34]	= 0.0f;
1661 	fp[35]	= 0.0f;
1662 	fp[36]	= 29.0f;
1663 	fp[37]	= 30.0f;
1664 	fp[38]	= 31.0f;
1665 	fp[39]	= 0.0f;
1666 	fp[40]	= 32.0f;
1667 	fp[41]	= 33.0f;
1668 	fp[42]	= 34.0f;
1669 	fp[43]	= 0.0f;
1670 	fp[44]	= 35.0f;
1671 	fp[45]	= 36.0f;
1672 	fp[46]	= 37.0f;
1673 	fp[47]	= 0.0f;
1674 	fp[48]	= 38.0f;
1675 	fp[49]	= 39.0f;
1676 	fp[50]	= 40.0f;
1677 	fp[51]	= 0.0f;
1678 	fp[52]	= 41.0f;
1679 	fp[53]	= 42.0f;
1680 	fp[54]	= 43.0f;
1681 	fp[55]	= 0.0f;
1682 	fp[56]	= 44.0f;
1683 	fp[57]	= 45.0f;
1684 	fp[58]	= 46.0f;
1685 	fp[59]	= 0.0f;
1686 	fp[60]	= 47.0f;
1687 	fp[61]	= 48.0f;
1688 	fp[62]	= 49.0f;
1689 	fp[63]	= 50.0f;
1690 	fp[64]	= 51.0f;
1691 	fp[65]	= 52.0f;
1692 	fp[66]	= 53.0f;
1693 	fp[67]	= 54.0f;
1694 	fp[68]	= 55.0f;
1695 	fp[69]	= 56.0f;
1696 	fp[70]	= 57.0f;
1697 	fp[71]	= 58.0f;
1698 	fp[72]	= 59.0f;
1699 	fp[73]	= 60.0f;
1700 	fp[74]	= 61.0f;
1701 	fp[75]	= 62.0f;
1702 	fp[76]	= 63.0f;
1703 	fp[77]	= 64.0f;
1704 	fp[78]	= 65.0f;
1705 	fp[79]	= 66.0f;
1706 	fp[80]	= 67.0f;
1707 	fp[81]	= 68.0f;
1708 	fp[82]	= 69.0f;
1709 	fp[83]	= 70.0f;
1710 	fp[84]	= 71.0f;
1711 	fp[85]	= 72.0f;
1712 	fp[86]	= 73.0f;
1713 	fp[87]	= 74.0f;
1714 	fp[88]	= 75.0f;
1715 	fp[89]	= 76.0f;
1716 	fp[90]	= 77.0f;
1717 	fp[91]	= 78.0f;
1718 
1719 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
1720 			  "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1721 			  "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_input;" NL
1722 			  "layout(std430, binding = 1) buffer Output {" NL "  float data0[2];" NL "  float data1[3];" NL
1723 			  "  vec2 data2;" NL "  float data3[5];" NL "  vec3 data4[2];" NL "  float data5[2];" NL
1724 			  "  mat2 data6[2];" NL "  mat3 data7[2];" NL "  mat4 data8[2];" NL "} g_output;" NL "void main() {" NL
1725 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
1726 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1727 			  "  g_output.data2 = g_input.data2;" NL
1728 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1729 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
1730 			  "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
1731 			  "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL
1732 			  "  for (int i = 0; i < g_input.data7.length(); ++i) g_output.data7[i] = g_input.data7[i];" NL
1733 			  "  for (int i = 0; i < g_input.data8.length(); ++i) g_output.data8[i] = g_input.data8[i];" NL "}";
1734 }
1735 
1736 class BasicStd430LayoutCase6VS : public BasicStdLayoutBaseVS
1737 {
GetInput(std::vector<GLubyte> & in_data)1738 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1739 	{
1740 		return GetInput430c6(in_data);
1741 	}
1742 };
1743 
1744 class BasicStd430LayoutCase6CS : public BasicStdLayoutBaseCS
1745 {
GetInput(std::vector<GLubyte> & in_data)1746 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1747 	{
1748 		return GetInput430c6(in_data);
1749 	}
1750 };
1751 
1752 //-----------------------------------------------------------------------------
1753 // 1.6.7 BasicStd430LayoutCase7
1754 //-----------------------------------------------------------------------------
GetInput430c7(std::vector<GLubyte> & in_data)1755 const char* GetInput430c7(std::vector<GLubyte>& in_data)
1756 {
1757 	in_data.resize(36 * 4);
1758 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1759 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1760 	ip[0]	 = 1;
1761 	ip[1]	 = 0;
1762 	ip[2]	 = 2;
1763 	ip[3]	 = 3;
1764 	fp[4]	 = 4.0f;
1765 	fp[5]	 = 0.0f;
1766 	fp[6]	 = 0.0f;
1767 	fp[7]	 = 0.0f;
1768 	fp[8]	 = 5.0f;
1769 	fp[9]	 = 6.0f;
1770 	fp[10]	= 7.0f;
1771 	fp[11]	= 0.0f;
1772 	fp[12]	= 8.0f;
1773 	fp[13]	= 0.0f;
1774 	fp[14]	= 0.0f;
1775 	fp[15]	= 0.0f;
1776 	fp[16]	= 9.0f;
1777 	fp[17]	= 10.0f;
1778 	fp[18]	= 11.0f;
1779 	fp[19]	= 0.0f;
1780 	ip[20]	= 12;
1781 	ip[21]	= 13;
1782 	ip[22]	= 14;
1783 	ip[23]	= 15;
1784 	fp[24]	= 16.0f;
1785 	fp[25]	= 0.0f;
1786 	fp[26]	= 0.0f;
1787 	fp[27]	= 0.0f;
1788 	fp[28]	= 17.0f;
1789 	fp[29]	= 18.0f;
1790 	fp[30]	= 19.0f;
1791 	fp[31]	= 0.0f;
1792 	ip[32]	= 20;
1793 	ip[33]	= 21;
1794 	ip[34]	= 22;
1795 	ip[35]	= 23;
1796 
1797 	return NL "struct Struct0 {" NL "  ivec2 m0;" NL "};" NL "struct Struct1 {" NL "  vec3 m0;" NL "};" NL
1798 			  "struct Struct3 {" NL "  int m0;" NL "};" NL "struct Struct2 {" NL "  float m0;" NL "  Struct1 m1;" NL
1799 			  "  Struct0 m2;" NL "  int m3;" NL "  Struct3 m4;" NL "};" NL
1800 			  "layout(std430, binding = 0) buffer Input {" NL "  int data0;" NL "  Struct0 data1;" NL
1801 			  "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_input;" NL
1802 			  "layout(std430, binding = 1) buffer Output {" NL "  int data0;" NL "  Struct0 data1;" NL
1803 			  "  float data2;" NL "  Struct1 data3;" NL "  Struct2 data4[2];" NL "} g_output;" NL "void main() {" NL
1804 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
1805 			  "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
1806 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL "}";
1807 }
1808 
1809 class BasicStd430LayoutCase7VS : public BasicStdLayoutBaseVS
1810 {
GetInput(std::vector<GLubyte> & in_data)1811 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1812 	{
1813 		return GetInput430c7(in_data);
1814 	}
1815 };
1816 
1817 class BasicStd430LayoutCase7CS : public BasicStdLayoutBaseCS
1818 {
GetInput(std::vector<GLubyte> & in_data)1819 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1820 	{
1821 		return GetInput430c7(in_data);
1822 	}
1823 };
1824 
1825 //-----------------------------------------------------------------------------
1826 // 1.7.1 BasicStd140LayoutCase1
1827 //-----------------------------------------------------------------------------
GetInput140c1(std::vector<GLubyte> & in_data)1828 const char* GetInput140c1(std::vector<GLubyte>& in_data)
1829 {
1830 	in_data.resize(8 * 4);
1831 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1832 	fp[0]	 = 1.0f;
1833 	fp[1]	 = 0.0f;
1834 	fp[2]	 = 0.0f;
1835 	fp[3]	 = 0.0f;
1836 	fp[4]	 = 2.0f;
1837 
1838 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "} g_input;" NL
1839 			  "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL "} g_output;" NL
1840 			  "void main() {" NL
1841 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL "}";
1842 }
1843 
1844 class BasicStd140LayoutCase1VS : public BasicStdLayoutBaseVS
1845 {
GetInput(std::vector<GLubyte> & in_data)1846 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1847 	{
1848 		return GetInput140c1(in_data);
1849 	}
1850 };
1851 
1852 class BasicStd140LayoutCase1CS : public BasicStdLayoutBaseCS
1853 {
GetInput(std::vector<GLubyte> & in_data)1854 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1855 	{
1856 		return GetInput140c1(in_data);
1857 	}
1858 };
1859 //-----------------------------------------------------------------------------
1860 // 1.7.2 BasicStd140LayoutCase2
1861 //-----------------------------------------------------------------------------
GetInput140c2(std::vector<GLubyte> & in_data)1862 const char* GetInput140c2(std::vector<GLubyte>& in_data)
1863 {
1864 	in_data.resize(20 * 4);
1865 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1866 	int*   ip = reinterpret_cast<int*>(&in_data[0]);
1867 	fp[0]	 = 1.0f;
1868 	fp[1]	 = 0.0f;
1869 	fp[2]	 = 0.0f;
1870 	fp[3]	 = 0.0f;
1871 	fp[4]	 = 2.0f;
1872 	fp[5]	 = 0.0f;
1873 	fp[6]	 = 0.0f;
1874 	fp[7]	 = 0.0f;
1875 	fp[8]	 = 3.0f;
1876 	fp[9]	 = 0.0f;
1877 	fp[10]	= 0.0f;
1878 	fp[11]	= 0.0f;
1879 	fp[12]	= 4.0f;
1880 	fp[13]	= 0.0f;
1881 	fp[14]	= 0.0f;
1882 	fp[15]	= 0.0f;
1883 	ip[16]	= 5;
1884 	ip[17]	= 6;
1885 
1886 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1887 			  "  ivec2 data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL
1888 			  "  float data1[3];" NL "  ivec2 data2;" NL "} g_output;" NL "void main() {" NL
1889 			  "  g_output.data0 = g_input.data0;" NL
1890 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1891 			  "  g_output.data2 = g_input.data2;" NL "}";
1892 }
1893 
1894 class BasicStd140LayoutCase2VS : public BasicStdLayoutBaseVS
1895 {
GetInput(std::vector<GLubyte> & in_data)1896 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1897 	{
1898 		return GetInput140c2(in_data);
1899 	}
1900 };
1901 
1902 class BasicStd140LayoutCase2CS : public BasicStdLayoutBaseCS
1903 {
GetInput(std::vector<GLubyte> & in_data)1904 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1905 	{
1906 		return GetInput140c2(in_data);
1907 	}
1908 };
1909 //-----------------------------------------------------------------------------
1910 // 1.7.3 BasicStd140LayoutCase3
1911 //-----------------------------------------------------------------------------
GetInput140c3(std::vector<GLubyte> & in_data)1912 const char* GetInput140c3(std::vector<GLubyte>& in_data)
1913 {
1914 	in_data.resize(32 * 4);
1915 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1916 	fp[0]	 = 1.0f;
1917 	fp[1]	 = 0.0f;
1918 	fp[2]	 = 0.0f;
1919 	fp[3]	 = 0.0f;
1920 	fp[4]	 = 2.0f;
1921 	fp[5]	 = 0.0f;
1922 	fp[6]	 = 0.0f;
1923 	fp[7]	 = 0.0f;
1924 	fp[8]	 = 3.0f;
1925 	fp[9]	 = 0.0f;
1926 	fp[10]	= 0.0f;
1927 	fp[11]	= 0.0f;
1928 	fp[12]	= 4.0f;
1929 	fp[13]	= 0.0f;
1930 	fp[14]	= 0.0f;
1931 	fp[15]	= 0.0f;
1932 	fp[16]	= 5.0f;
1933 	fp[17]	= 6.0f;
1934 	fp[18]	= 0.0f;
1935 	fp[19]	= 0.0f;
1936 	fp[20]	= 7.0f;
1937 	fp[21]	= 8.0f;
1938 	fp[22]	= 9.0f;
1939 	fp[23]	= 0.0f;
1940 	fp[24]	= 10.0f;
1941 	fp[25]	= 11.0f;
1942 	fp[26]	= 12.0f;
1943 	fp[27]	= 0.0f;
1944 	fp[28]	= 13.0f;
1945 
1946 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0;" NL "  float data1[3];" NL
1947 			  "  vec2 data2;" NL "  readonly vec3 data3[2];" NL "  float data4;" NL "} g_input;" NL
1948 			  "layout(std140, binding = 1) buffer Output {" NL "  float data0;" NL "  float data1[3];" NL
1949 			  "  vec2 data2;" NL "  vec3 data3[2];" NL "  float data4;" NL "} g_output;" NL "void main() {" NL
1950 			  "  g_output.data0 = g_input.data0;" NL
1951 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
1952 			  "  g_output.data2 = g_input.data2;" NL
1953 			  "  for (int i = 0; i < g_input.data3.length(); ++i) g_output.data3[i] = g_input.data3[i];" NL
1954 			  "  g_output.data4 = g_input.data4;" NL "}";
1955 }
1956 
1957 class BasicStd140LayoutCase3VS : public BasicStdLayoutBaseVS
1958 {
GetInput(std::vector<GLubyte> & in_data)1959 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1960 	{
1961 		return GetInput140c3(in_data);
1962 	}
1963 };
1964 
1965 class BasicStd140LayoutCase3CS : public BasicStdLayoutBaseCS
1966 {
GetInput(std::vector<GLubyte> & in_data)1967 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
1968 	{
1969 		return GetInput140c3(in_data);
1970 	}
1971 };
1972 
1973 //-----------------------------------------------------------------------------
1974 // 1.7.4 BasicStd140LayoutCase4
1975 //-----------------------------------------------------------------------------
GetInput140c4(std::vector<GLubyte> & in_data)1976 const char* GetInput140c4(std::vector<GLubyte>& in_data)
1977 {
1978 	in_data.resize(28 * 4);
1979 	float* fp = reinterpret_cast<float*>(&in_data[0]);
1980 	fp[0]	 = 1.0f;
1981 	fp[1]	 = 2.0f;
1982 	fp[2]	 = 0.0f;
1983 	fp[3]	 = 0.0f;
1984 	fp[4]	 = 3.0f;
1985 	fp[5]	 = 4.0f;
1986 	fp[6]	 = 0.0f;
1987 	fp[7]	 = 0.0f;
1988 	fp[8]	 = 5.0f;
1989 	fp[9]	 = 6.0f;
1990 	fp[10]	= 0.0f;
1991 	fp[11]	= 0.0f;
1992 	fp[12]	= 7.0f;
1993 	fp[13]	= 8.0f;
1994 	fp[14]	= 0.0f;
1995 	fp[15]	= 0.0f;
1996 	fp[16]	= 9.0f;
1997 	fp[17]	= 10.0f;
1998 	fp[18]	= 11.0f;
1999 	fp[19]	= 0.0f;
2000 	fp[20]	= 12.0f;
2001 	fp[21]	= 13.0f;
2002 	fp[22]	= 14.0f;
2003 	fp[23]	= 0.0f;
2004 	fp[24]	= 15.0f;
2005 
2006 	return NL "layout(std140, binding = 0) buffer Input {" NL "  mat4x2 data0;" NL "  mat2x3 data1;" NL
2007 			  "  float data2;" NL "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  mat4x2 data0;" NL
2008 			  "  mat2x3 data1;" NL "  float data2;" NL "} g_output;" NL "void main() {" NL
2009 			  "  g_output.data0 = g_input.data0;" NL "  g_output.data1 = g_input.data1;" NL
2010 			  "  g_output.data2 = g_input.data2;" NL "}";
2011 }
2012 
2013 class BasicStd140LayoutCase4VS : public BasicStdLayoutBaseVS
2014 {
GetInput(std::vector<GLubyte> & in_data)2015 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2016 	{
2017 		return GetInput140c4(in_data);
2018 	}
2019 };
2020 
2021 class BasicStd140LayoutCase4CS : public BasicStdLayoutBaseCS
2022 {
GetInput(std::vector<GLubyte> & in_data)2023 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2024 	{
2025 		return GetInput140c4(in_data);
2026 	}
2027 };
2028 //-----------------------------------------------------------------------------
2029 // 1.7.5 BasicStd140LayoutCase5
2030 //-----------------------------------------------------------------------------
GetInput140c5(std::vector<GLubyte> & in_data)2031 const char* GetInput140c5(std::vector<GLubyte>& in_data)
2032 {
2033 	in_data.resize(8 * 4);
2034 	float* fp = reinterpret_cast<float*>(&in_data[0]);
2035 	fp[0]	 = 1.0f;
2036 	fp[1]	 = 2.0f;
2037 	fp[2]	 = 3.0f;
2038 	fp[3]	 = 4.0f;
2039 	fp[4]	 = 5.0f;
2040 	fp[5]	 = 6.0f;
2041 	fp[6]	 = 7.0f;
2042 	fp[7]	 = 8.0f;
2043 
2044 	return NL "layout(std140, binding = 0, row_major) buffer Input {" NL "  mat4x2 data0;" NL "} g_input;" NL
2045 			  "layout(std140, binding = 1, row_major) buffer Output {" NL "  mat4x2 data0;" NL "} g_output;" NL
2046 			  "void main() {" NL "  g_output.data0 = g_input.data0;" NL "}";
2047 }
2048 
2049 class BasicStd140LayoutCase5VS : public BasicStdLayoutBaseVS
2050 {
GetInput(std::vector<GLubyte> & in_data)2051 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2052 	{
2053 		return GetInput140c5(in_data);
2054 	}
2055 };
2056 
2057 class BasicStd140LayoutCase5CS : public BasicStdLayoutBaseCS
2058 {
GetInput(std::vector<GLubyte> & in_data)2059 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2060 	{
2061 		return GetInput140c5(in_data);
2062 	}
2063 };
2064 
2065 //-----------------------------------------------------------------------------
2066 // 1.7.6 BasicStd140LayoutCase6
2067 //-----------------------------------------------------------------------------
GetInput140c6(std::vector<GLubyte> & in_data)2068 const char* GetInput140c6(std::vector<GLubyte>& in_data)
2069 {
2070 	in_data.resize(96 * 4);
2071 	float* fp = reinterpret_cast<float*>(&in_data[0]);
2072 	fp[0]	 = 1.0f;
2073 	fp[1]	 = 0.0f;
2074 	fp[2]	 = 0.0f;
2075 	fp[3]	 = 0.0f;
2076 	fp[4]	 = 2.0f;
2077 	fp[5]	 = 0.0f;
2078 	fp[6]	 = 0.0f;
2079 	fp[7]	 = 0.0f;
2080 	fp[8]	 = 3.0f;
2081 	fp[9]	 = 0.0f;
2082 	fp[10]	= 0.0f;
2083 	fp[11]	= 0.0f;
2084 	fp[12]	= 4.0f;
2085 	fp[13]	= 0.0f;
2086 	fp[14]	= 0.0f;
2087 	fp[15]	= 0.0f;
2088 	fp[16]	= 5.0f;
2089 	fp[17]	= 0.0f;
2090 	fp[18]	= 0.0f;
2091 	fp[19]	= 0.0f;
2092 	fp[20]	= 6.0f;
2093 	fp[21]	= 7.0f;
2094 	fp[22]	= 8.0f;
2095 	fp[23]	= 9.0f;
2096 	fp[24]	= 10.0f;
2097 	fp[25]	= 11.0f;
2098 	fp[26]	= 0.0f;
2099 	fp[27]	= 0.0f;
2100 	fp[28]	= 12.0f;
2101 	fp[29]	= 13.0f;
2102 	fp[30]	= 0.0f;
2103 	fp[31]	= 0.0f;
2104 	fp[32]	= 14.0f;
2105 	fp[33]	= 15.0f;
2106 	fp[34]	= 0.0f;
2107 	fp[35]	= 0.0f;
2108 	fp[36]	= 16.0f;
2109 	fp[37]	= 17.0f;
2110 	fp[38]	= 0.0f;
2111 	fp[39]	= 0.0f;
2112 	fp[40]	= 18.0f;
2113 	fp[41]	= 19.0f;
2114 	fp[42]	= 20.0f;
2115 	fp[43]	= 0.0f;
2116 	fp[44]	= 21.0f;
2117 	fp[45]	= 22.0f;
2118 	fp[46]	= 23.0f;
2119 	fp[47]	= 0.0f;
2120 	fp[48]	= 24.0f;
2121 	fp[49]	= 25.0f;
2122 	fp[50]	= 26.0f;
2123 	fp[51]	= 0.0f;
2124 	fp[52]	= 27.0f;
2125 	fp[53]	= 28.0f;
2126 	fp[54]	= 29.0f;
2127 	fp[55]	= 0.0f;
2128 	fp[56]	= 30.0f;
2129 	fp[57]	= 31.0f;
2130 	fp[58]	= 32.0f;
2131 	fp[59]	= 0.0f;
2132 	fp[60]	= 33.0f;
2133 	fp[61]	= 34.0f;
2134 	fp[62]	= 35.0f;
2135 	fp[63]	= 0.0f;
2136 	fp[64]	= 36.0f;
2137 	fp[65]	= 37.0f;
2138 	fp[66]	= 38.0f;
2139 	fp[67]	= 39.0f;
2140 	fp[68]	= 40.0f;
2141 	fp[69]	= 41.0f;
2142 	fp[70]	= 42.0f;
2143 	fp[71]	= 43.0f;
2144 	fp[72]	= 44.0f;
2145 	fp[73]	= 45.0f;
2146 	fp[74]	= 46.0f;
2147 	fp[75]	= 47.0f;
2148 	fp[76]	= 48.0f;
2149 	fp[77]	= 49.0f;
2150 	fp[78]	= 50.0f;
2151 	fp[79]	= 51.0f;
2152 	fp[80]	= 52.0f;
2153 	fp[81]	= 68.0f;
2154 	fp[82]	= 69.0f;
2155 	fp[83]	= 70.0f;
2156 	fp[84]	= 56.0f;
2157 	fp[85]	= 72.0f;
2158 	fp[86]	= 73.0f;
2159 	fp[87]	= 74.0f;
2160 	fp[88]	= 60.0f;
2161 	fp[89]	= 76.0f;
2162 	fp[90]	= 77.0f;
2163 	fp[91]	= 78.0f;
2164 	fp[92]	= 64.0f;
2165 	fp[93]	= 80.0f;
2166 	fp[94]	= 81.0f;
2167 	fp[95]	= 82.0f;
2168 
2169 	return NL "layout(std140, binding = 0) buffer Input {" NL "  float data0[2];" NL "  float data1[3];" NL
2170 			  "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL "  mat4 data6[2];" NL
2171 			  "} g_input;" NL "layout(std140, binding = 1) buffer Output {" NL "  float data0[2];" NL
2172 			  "  float data1[3];" NL "  vec2 data2;" NL "  vec2 data3;" NL "  mat2 data4[2];" NL "  mat3 data5[2];" NL
2173 			  "  mat4 data6[2];" NL "} g_output;" NL "void main() {" NL
2174 			  "  for (int i = 0; i < g_input.data0.length(); ++i) g_output.data0[i] = g_input.data0[i];" NL
2175 			  "  for (int i = 0; i < g_input.data1.length(); ++i) g_output.data1[i] = g_input.data1[i];" NL
2176 			  "  g_output.data2 = g_input.data2;" NL "  g_output.data3 = g_input.data3;" NL
2177 			  "  for (int i = 0; i < g_input.data4.length(); ++i) g_output.data4[i] = g_input.data4[i];" NL
2178 			  "  for (int i = 0; i < g_input.data5.length(); ++i) g_output.data5[i] = g_input.data5[i];" NL
2179 			  "  for (int i = 0; i < g_input.data6.length(); ++i) g_output.data6[i] = g_input.data6[i];" NL "}";
2180 }
2181 
2182 class BasicStd140LayoutCase6VS : public BasicStdLayoutBaseVS
2183 {
GetInput(std::vector<GLubyte> & in_data)2184 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2185 	{
2186 		return GetInput140c6(in_data);
2187 	}
2188 };
2189 
2190 class BasicStd140LayoutCase6CS : public BasicStdLayoutBaseCS
2191 {
GetInput(std::vector<GLubyte> & in_data)2192 	virtual const char* GetInput(std::vector<GLubyte>& in_data)
2193 	{
2194 		return GetInput140c6(in_data);
2195 	}
2196 };
2197 
2198 //-----------------------------------------------------------------------------
2199 // 1.8.1 BasicAtomicCase1
2200 //-----------------------------------------------------------------------------
2201 class BasicAtomicCase1 : public ShaderStorageBufferObjectBase
2202 {
2203 	GLuint m_program;
2204 	GLuint m_storage_buffer[6];
2205 	GLuint m_vertex_array;
2206 	GLuint m_vertex_buffer;
2207 
Setup()2208 	virtual long Setup()
2209 	{
2210 		m_program = 0;
2211 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2212 		m_vertex_array  = 0;
2213 		m_vertex_buffer = 0;
2214 		return NO_ERROR;
2215 	}
2216 
Run()2217 	virtual long Run()
2218 	{
2219 		if (!SupportedInVS(2))
2220 			return NOT_SUPPORTED;
2221 		if (!SupportedInGS(2))
2222 			return NOT_SUPPORTED;
2223 
2224 		const char* const glsl_vs =
2225 			NL "layout(location = 0) in vec4 g_in_position;" NL
2226 			   "layout(std430, binding = 0) coherent buffer VSuint {" NL "  uint g_uint_out[4];" NL "};" NL
2227 			   "layout(std430, binding = 1) coherent buffer VSint {" NL "  int data[4];" NL "} g_int_out;" NL
2228 			   "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2229 			   "  gl_Position = g_in_position;" NL NL
2230 			   "  if (atomicExchange(g_uint_out[gl_VertexID], g_uint_value[1]) != 0u) return;" NL
2231 			   "  if (atomicAdd(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2232 			   "  if (atomicMin(g_uint_out[gl_VertexID], g_uint_value[1]) != 3u) return;" NL
2233 			   "  if (atomicMax(g_uint_out[gl_VertexID], g_uint_value[2]) != 1u) return;" NL
2234 			   "  if (atomicAnd(g_uint_out[gl_VertexID], g_uint_value[3]) != 2u) return;" NL
2235 			   "  if (atomicOr(g_uint_out[gl_VertexID], g_uint_value[4]) != 0u) return;" NL
2236 			   "  if (g_uint_value[0] > 0u) {" NL
2237 			   "    if (atomicXor(g_uint_out[gl_VertexID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2238 			   "  if (atomicCompSwap(g_uint_out[gl_VertexID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2239 			   "    g_uint_out[gl_VertexID] = 1u;" NL "    return;" NL "  }" NL NL
2240 			   "  if (atomicExchange(g_int_out.data[gl_VertexID], 1) != 0) return;" NL
2241 			   "  if (atomicAdd(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2242 			   "  if (atomicMin(g_int_out.data[gl_VertexID], 1) != 3) return;" NL
2243 			   "  if (atomicMax(g_int_out.data[gl_VertexID], 2) != 1) return;" NL
2244 			   "  if (atomicAnd(g_int_out.data[gl_VertexID], 0x1) != 2) return;" NL
2245 			   "  if (atomicOr(g_int_out.data[gl_VertexID], 0x3) != 0) return;" NL
2246 			   "  if (atomicXor(g_int_out.data[gl_VertexID], 0x1) != 3) return;" NL
2247 			   "  if (atomicCompSwap(g_int_out.data[gl_VertexID], 0x2, 0x7) != 2) {" NL
2248 			   "    g_int_out.data[gl_VertexID] = 1;" NL "    return;" NL "  }" NL "}";
2249 
2250 		const char* const glsl_gs = NL
2251 			"layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2252 			"layout(std430, binding = 2) coherent buffer GSuint {" NL "  uint data[4];" NL "} g_uint_gs;" NL
2253 			"layout(std430, binding = 3) coherent buffer GSint {" NL "  int data[4];" NL "} g_int_gs;" NL
2254 			"uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2255 			"  gl_Position = gl_in[0].gl_Position;" NL "  gl_PrimitiveID = gl_PrimitiveIDIn;" NL "  EmitVertex();" NL NL
2256 			"  if (atomicExchange(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 0u) return;" NL
2257 			"  if (atomicAdd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2258 			"  if (atomicMin(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[1]) != 3u) return;" NL
2259 			"  if (atomicMax(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[2]) != 1u) return;" NL
2260 			"  if (atomicAnd(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[3]) != 2u) return;" NL
2261 			"  if (atomicOr(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[4]) != 0u) return;" NL
2262 			"  if (g_uint_value[0] > 0u) {" NL
2263 			"    if (atomicXor(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[5]) != 3u) return;" NL "  }" NL
2264 			"  if (atomicCompSwap(g_uint_gs.data[gl_PrimitiveIDIn], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2265 			"    g_uint_gs.data[gl_PrimitiveIDIn] = 1u;" NL "    return;" NL "  }" NL NL
2266 			"  if (atomicExchange(g_int_gs.data[gl_PrimitiveIDIn], 1) != 0) return;" NL
2267 			"  if (atomicAdd(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2268 			"  if (atomicMin(g_int_gs.data[gl_PrimitiveIDIn], 1) != 3) return;" NL
2269 			"  if (atomicMax(g_int_gs.data[gl_PrimitiveIDIn], 2) != 1) return;" NL
2270 			"  if (atomicAnd(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 2) return;" NL
2271 			"  if (atomicOr(g_int_gs.data[gl_PrimitiveIDIn], 0x3) != 0) return;" NL
2272 			"  if (atomicXor(g_int_gs.data[gl_PrimitiveIDIn], 0x1) != 3) return;" NL
2273 			"  if (atomicCompSwap(g_int_gs.data[gl_PrimitiveIDIn], 0x2, 0x7) != 2) {" NL
2274 			"    g_int_gs.data[gl_PrimitiveIDIn] = 1;" NL "    return;" NL "  }" NL "}";
2275 
2276 		const char* const glsl_fs =
2277 			NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 4) coherent buffer FSuint {" NL
2278 			   "  uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 5) coherent buffer FSint {" NL
2279 			   "  int data[4];" NL "} g_int_fs;" NL
2280 			   "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2281 			   "  g_fs_out = vec4(0, 1, 0, 1);" NL NL
2282 			   "  if (atomicExchange(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2283 			   "  if (atomicAdd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2284 			   "  if (atomicMin(g_uint_fs.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2285 			   "  if (atomicMax(g_uint_fs.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2286 			   "  if (atomicAnd(g_uint_fs.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2287 			   "  if (atomicOr(g_uint_fs.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2288 			   "  if (g_uint_value[0] > 0u) {" NL
2289 			   "    if (atomicXor(g_uint_fs.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2290 			   "  if (atomicCompSwap(g_uint_fs.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2291 			   "    g_uint_fs.data[gl_PrimitiveID] = 1u;" NL "    return;" NL "  }" NL NL
2292 			   "  if (atomicExchange(g_int_fs.data[gl_PrimitiveID], 1) != 0) return;" NL
2293 			   "  if (atomicAdd(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2294 			   "  if (atomicMin(g_int_fs.data[gl_PrimitiveID], 1) != 3) return;" NL
2295 			   "  if (atomicMax(g_int_fs.data[gl_PrimitiveID], 2) != 1) return;" NL
2296 			   "  if (atomicAnd(g_int_fs.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2297 			   "  if (atomicOr(g_int_fs.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2298 			   "  if (atomicXor(g_int_fs.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2299 			   "  if (atomicCompSwap(g_int_fs.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2300 			   "    g_int_fs.data[gl_PrimitiveID] = 1;" NL "    return;" NL "  }" NL "}";
2301 		m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2302 		glLinkProgram(m_program);
2303 		if (!CheckProgram(m_program))
2304 			return ERROR;
2305 
2306 		glGenBuffers(6, m_storage_buffer);
2307 		for (GLuint i = 0; i < 6; ++i)
2308 		{
2309 			const int data[4] = { 0 };
2310 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2311 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2312 		}
2313 
2314 		/* vertex buffer */
2315 		{
2316 			const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2317 			glGenBuffers(1, &m_vertex_buffer);
2318 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2319 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2320 			glBindBuffer(GL_ARRAY_BUFFER, 0);
2321 		}
2322 
2323 		glGenVertexArrays(1, &m_vertex_array);
2324 		glBindVertexArray(m_vertex_array);
2325 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2326 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2327 		glBindBuffer(GL_ARRAY_BUFFER, 0);
2328 		glEnableVertexAttribArray(0);
2329 		glBindVertexArray(0);
2330 
2331 		glClear(GL_COLOR_BUFFER_BIT);
2332 		glUseProgram(m_program);
2333 		glBindVertexArray(m_vertex_array);
2334 		glDrawArrays(GL_POINTS, 0, 4);
2335 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2336 
2337 		for (int ii = 0; ii < 3; ++ii)
2338 		{
2339 			/* uint data */
2340 			{
2341 				GLuint data[4];
2342 				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2343 				glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2344 				for (GLuint i = 0; i < 4; ++i)
2345 				{
2346 					if (data[i] != 7)
2347 					{
2348 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2349 															<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2350 						return ERROR;
2351 					}
2352 				}
2353 			}
2354 			/* int data */
2355 			{
2356 				GLint data[4];
2357 				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2358 				glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2359 				for (GLint i = 0; i < 4; ++i)
2360 				{
2361 					if (data[i] != 7)
2362 					{
2363 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2364 															<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2365 						return ERROR;
2366 					}
2367 				}
2368 			}
2369 		}
2370 		return NO_ERROR;
2371 	}
2372 
Cleanup()2373 	virtual long Cleanup()
2374 	{
2375 		glUseProgram(0);
2376 		glDeleteProgram(m_program);
2377 		glDeleteBuffers(6, m_storage_buffer);
2378 		glDeleteBuffers(1, &m_vertex_buffer);
2379 		glDeleteVertexArrays(1, &m_vertex_array);
2380 		return NO_ERROR;
2381 	}
2382 };
2383 
2384 class BasicAtomicCase1CS : public ShaderStorageBufferObjectBase
2385 {
2386 	GLuint m_program;
2387 	GLuint m_storage_buffer[2];
2388 
Setup()2389 	virtual long Setup()
2390 	{
2391 		m_program = 0;
2392 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2393 		return NO_ERROR;
2394 	}
2395 
Run()2396 	virtual long Run()
2397 	{
2398 		const char* const glsl_cs =
2399 			NL "layout(local_size_x = 4) in;" NL "layout(std430, binding = 2) coherent buffer FSuint {" NL
2400 			   "  uint data[4];" NL "} g_uint_fs;" NL "layout(std430, binding = 3) coherent buffer FSint {" NL
2401 			   "  int data[4];" NL "} g_int_fs;" NL "uniform uint g_uint_value[8];" NL "void main() {" NL
2402 			   "  if (atomicExchange(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 0u) return;" NL
2403 			   "  if (atomicAdd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2404 			   "  if (atomicMin(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[1]) != 3u) return;" NL
2405 			   "  if (atomicMax(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[2]) != 1u) return;" NL
2406 			   "  if (atomicAnd(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[3]) != 2u) return;" NL
2407 			   "  if (atomicOr(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[4]) != 0u) return;" NL
2408 			   "  if (g_uint_value[0] > 0u) {" NL
2409 			   "    if (atomicXor(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[5]) != 3u) return;" NL "  }" NL
2410 			   "  if (atomicCompSwap(g_uint_fs.data[gl_LocalInvocationIndex], g_uint_value[6], g_uint_value[7]) != 2u) "
2411 			   "{" NL "    g_uint_fs.data[gl_LocalInvocationIndex] = 1u;" NL "    return;" NL "  }" NL
2412 			   "  if (atomicExchange(g_int_fs.data[gl_LocalInvocationIndex], 1) != 0) return;" NL
2413 			   "  if (atomicAdd(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2414 			   "  if (atomicMin(g_int_fs.data[gl_LocalInvocationIndex], 1) != 3) return;" NL
2415 			   "  if (atomicMax(g_int_fs.data[gl_LocalInvocationIndex], 2) != 1) return;" NL
2416 			   "  if (atomicAnd(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 2) return;" NL
2417 			   "  if (atomicOr(g_int_fs.data[gl_LocalInvocationIndex], 0x3) != 0) return;" NL
2418 			   "  if (atomicXor(g_int_fs.data[gl_LocalInvocationIndex], 0x1) != 3) return;" NL
2419 			   "  if (atomicCompSwap(g_int_fs.data[gl_LocalInvocationIndex], 0x2, 0x7) != 2) {" NL
2420 			   "    g_int_fs.data[gl_LocalInvocationIndex] = 1;" NL "    return;" NL "  }" NL "}";
2421 		m_program = CreateProgramCS(glsl_cs);
2422 		glLinkProgram(m_program);
2423 		if (!CheckProgram(m_program))
2424 			return ERROR;
2425 
2426 		glGenBuffers(2, m_storage_buffer);
2427 		for (GLuint i = 0; i < 2; ++i)
2428 		{
2429 			const int data[4] = { 0 };
2430 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 2, m_storage_buffer[i]);
2431 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2432 		}
2433 
2434 		glUseProgram(m_program);
2435 		GLuint unif[8] = { 3, 1, 2, 1, 3, 1, 2, 7 };
2436 		glUniform1uiv(glGetUniformLocation(m_program, "g_uint_value[0]"), 8, unif);
2437 		glDispatchCompute(1, 1, 1);
2438 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2439 
2440 		/* uint data */
2441 		{
2442 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
2443 			GLuint* data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2444 			if (!data)
2445 				return ERROR;
2446 			for (GLuint i = 0; i < 4; ++i)
2447 			{
2448 				if (data[i] != 7)
2449 				{
2450 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2451 														<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2452 					return ERROR;
2453 				}
2454 			}
2455 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2456 		}
2457 		/* int data */
2458 		{
2459 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
2460 			GLint* data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
2461 			if (!data)
2462 				return ERROR;
2463 			for (GLint i = 0; i < 4; ++i)
2464 			{
2465 				if (data[i] != 7)
2466 				{
2467 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2468 														<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2469 					return ERROR;
2470 				}
2471 			}
2472 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2473 		}
2474 		return NO_ERROR;
2475 	}
2476 
Cleanup()2477 	virtual long Cleanup()
2478 	{
2479 		glUseProgram(0);
2480 		glDeleteProgram(m_program);
2481 		glDeleteBuffers(2, m_storage_buffer);
2482 		return NO_ERROR;
2483 	}
2484 };
2485 //-----------------------------------------------------------------------------
2486 // 1.8.2 BasicAtomicCase2
2487 //-----------------------------------------------------------------------------
2488 class BasicAtomicCase2 : public ShaderStorageBufferObjectBase
2489 {
2490 	GLuint m_program;
2491 	GLuint m_storage_buffer[4];
2492 	GLuint m_vertex_array;
2493 	GLuint m_vertex_buffer;
2494 
Setup()2495 	virtual long Setup()
2496 	{
2497 		m_program = 0;
2498 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2499 		m_vertex_array  = 0;
2500 		m_vertex_buffer = 0;
2501 		return NO_ERROR;
2502 	}
2503 
Run()2504 	virtual long Run()
2505 	{
2506 		if (!SupportedInTCS(2))
2507 			return NOT_SUPPORTED;
2508 		if (!SupportedInTES(2))
2509 			return NOT_SUPPORTED;
2510 
2511 		const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
2512 									   "  gl_Position = g_in_position;" NL "}";
2513 
2514 		const char* const glsl_tcs = NL
2515 			"layout(vertices = 1) out;" NL "layout(std430, binding = 0) buffer TCSuint {" NL "  uint g_uint_out[1];" NL
2516 			"};" NL "layout(std430, binding = 1) buffer TCSint {" NL "  int data[1];" NL "} g_int_out;" NL
2517 			"uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2518 			"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;" NL
2519 			"  if (gl_InvocationID == 0) {" NL "    gl_TessLevelInner[0] = 1.0;" NL "    gl_TessLevelInner[1] = 1.0;" NL
2520 			"    gl_TessLevelOuter[0] = 1.0;" NL "    gl_TessLevelOuter[1] = 1.0;" NL
2521 			"    gl_TessLevelOuter[2] = 1.0;" NL "    gl_TessLevelOuter[3] = 1.0;" NL "  }" NL
2522 			"  if (atomicAdd(g_uint_out[gl_InvocationID], g_uint_value[0]) != 0u) return;" NL
2523 			"  if (atomicExchange(g_uint_out[gl_InvocationID], g_uint_value[0]) != 3u) return;" NL
2524 			"  if (atomicMin(g_uint_out[gl_InvocationID], g_uint_value[1]) != 3u) return;" NL
2525 			"  if (atomicMax(g_uint_out[gl_InvocationID], g_uint_value[2]) != 1u) return;" NL
2526 			"  if (atomicAnd(g_uint_out[gl_InvocationID], g_uint_value[3]) != 2u) return;" NL
2527 			"  if (atomicOr(g_uint_out[gl_InvocationID], g_uint_value[4]) != 0u) return;" NL
2528 			"  if (g_uint_value[0] > 0u) {" NL
2529 			"    if (atomicXor(g_uint_out[gl_InvocationID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2530 			"  if (atomicCompSwap(g_uint_out[gl_InvocationID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2531 			"    g_uint_out[gl_InvocationID] = 1u;" NL "    return;" NL "  }" NL NL
2532 			"  if (atomicAdd(g_int_out.data[gl_InvocationID], 3) != 0) return;" NL
2533 			"  if (atomicExchange(g_int_out.data[gl_InvocationID], 3) != 3) return;" NL
2534 			"  if (atomicMin(g_int_out.data[gl_InvocationID], 1) != 3) return;" NL
2535 			"  if (atomicMax(g_int_out.data[gl_InvocationID], 2) != 1) return;" NL
2536 			"  if (atomicAnd(g_int_out.data[gl_InvocationID], 0x1) != 2) return;" NL
2537 			"  if (atomicOr(g_int_out.data[gl_InvocationID], 0x3) != 0) return;" NL
2538 			"  if (atomicXor(g_int_out.data[gl_InvocationID], 0x1) != 3) return;" NL
2539 			"  if (atomicCompSwap(g_int_out.data[gl_InvocationID], 0x2, 0x7) != 2) {" NL
2540 			"    g_int_out.data[gl_InvocationID] = 1;" NL "    return;" NL "  }" NL "}";
2541 
2542 		const char* const glsl_tes =
2543 			NL "layout(quads, point_mode) in;" NL "layout(std430, binding = 2) buffer TESuint {" NL "  uint data[1];" NL
2544 			   "} g_uint_tes;" NL "layout(std430, binding = 3) buffer TESint {" NL "  int data[1];" NL "} g_int_tes;" NL
2545 			   "uniform uint g_uint_value[8] = uint[8](3u, 1u, 2u, 0x1u, 0x3u, 0x1u, 0x2u, 0x7u);" NL "void main() {" NL
2546 			   "  gl_Position = gl_in[0].gl_Position;" NL NL
2547 			   "  if (atomicExchange(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 0u) return;" NL
2548 			   "  if (atomicAdd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2549 			   "  if (atomicMin(g_uint_tes.data[gl_PrimitiveID], g_uint_value[1]) != 3u) return;" NL
2550 			   "  if (atomicMax(g_uint_tes.data[gl_PrimitiveID], g_uint_value[2]) != 1u) return;" NL
2551 			   "  if (atomicAnd(g_uint_tes.data[gl_PrimitiveID], g_uint_value[3]) != 2u) return;" NL
2552 			   "  if (atomicOr(g_uint_tes.data[gl_PrimitiveID], g_uint_value[4]) != 0u) return;" NL
2553 			   "  if (g_uint_value[0] > 0u) {" NL
2554 			   "    if (atomicXor(g_uint_tes.data[gl_PrimitiveID], g_uint_value[5]) != 3u) return;" NL "  }" NL
2555 			   "  if (atomicCompSwap(g_uint_tes.data[gl_PrimitiveID], g_uint_value[6], g_uint_value[7]) != 2u) {" NL
2556 			   "    g_uint_tes.data[gl_PrimitiveID] = 1u;" NL "    return;" NL "  }" NL NL
2557 			   "  if (atomicExchange(g_int_tes.data[gl_PrimitiveID], 1) != 0) return;" NL
2558 			   "  if (atomicAdd(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2559 			   "  if (atomicMin(g_int_tes.data[gl_PrimitiveID], 1) != 3) return;" NL
2560 			   "  if (atomicMax(g_int_tes.data[gl_PrimitiveID], 2) != 1) return;" NL
2561 			   "  if (atomicAnd(g_int_tes.data[gl_PrimitiveID], 0x1) != 2) return;" NL
2562 			   "  if (atomicOr(g_int_tes.data[gl_PrimitiveID], 0x3) != 0) return;" NL
2563 			   "  if (atomicXor(g_int_tes.data[gl_PrimitiveID], 0x1) != 3) return;" NL
2564 			   "  if (atomicCompSwap(g_int_tes.data[gl_PrimitiveID], 0x2, 0x7) != 2) {" NL
2565 			   "    g_int_tes.data[gl_PrimitiveID] = 1;" NL "    return;" NL "  }" NL "}";
2566 
2567 		const char* const glsl_fs =
2568 			NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
2569 
2570 		m_program = CreateProgram(glsl_vs, glsl_tcs, glsl_tes, "", glsl_fs);
2571 		glLinkProgram(m_program);
2572 		if (!CheckProgram(m_program))
2573 			return ERROR;
2574 
2575 		glGenBuffers(4, m_storage_buffer);
2576 		for (GLuint i = 0; i < 4; ++i)
2577 		{
2578 			const int data[1] = { 0 };
2579 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
2580 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
2581 		}
2582 
2583 		/* vertex buffer */
2584 		{
2585 			const float data[2] = { 0.0f, 0.0f };
2586 			glGenBuffers(1, &m_vertex_buffer);
2587 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2588 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2589 			glBindBuffer(GL_ARRAY_BUFFER, 0);
2590 		}
2591 
2592 		glGenVertexArrays(1, &m_vertex_array);
2593 		glBindVertexArray(m_vertex_array);
2594 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2595 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2596 		glBindBuffer(GL_ARRAY_BUFFER, 0);
2597 		glEnableVertexAttribArray(0);
2598 		glBindVertexArray(0);
2599 
2600 		glClear(GL_COLOR_BUFFER_BIT);
2601 		glUseProgram(m_program);
2602 		glBindVertexArray(m_vertex_array);
2603 		glPatchParameteri(GL_PATCH_VERTICES, 1);
2604 		glDrawArrays(GL_PATCHES, 0, 1);
2605 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2606 
2607 		for (int ii = 0; ii < 2; ++ii)
2608 		{
2609 			/* uint data */
2610 			{
2611 				GLuint data[1];
2612 				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 0]);
2613 				glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2614 				for (GLuint i = 0; i < 1; ++i)
2615 				{
2616 					if (data[i] != 7)
2617 					{
2618 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2619 															<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2620 						return ERROR;
2621 					}
2622 				}
2623 			}
2624 			/* int data */
2625 			{
2626 				GLint data[1];
2627 				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[ii * 2 + 1]);
2628 				glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
2629 				for (GLint i = 0; i < 1; ++i)
2630 				{
2631 					if (data[i] != 7)
2632 					{
2633 						m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2634 															<< data[i] << " should be 7." << tcu::TestLog::EndMessage;
2635 						return ERROR;
2636 					}
2637 				}
2638 			}
2639 		}
2640 		return NO_ERROR;
2641 	}
2642 
Cleanup()2643 	virtual long Cleanup()
2644 	{
2645 		glPatchParameteri(GL_PATCH_VERTICES, 3);
2646 		glUseProgram(0);
2647 		glDeleteProgram(m_program);
2648 		glDeleteBuffers(4, m_storage_buffer);
2649 		glDeleteBuffers(1, &m_vertex_buffer);
2650 		glDeleteVertexArrays(1, &m_vertex_array);
2651 		return NO_ERROR;
2652 	}
2653 };
2654 
2655 //-----------------------------------------------------------------------------
2656 // 1.8.3 BasicAtomicCase3
2657 //-----------------------------------------------------------------------------
2658 class BasicAtomicCase3 : public ShaderStorageBufferObjectBase
2659 {
2660 	GLuint m_program;
2661 	GLuint m_storage_buffer;
2662 	GLuint m_vertex_array;
2663 	GLuint m_vertex_buffer;
2664 
Setup()2665 	virtual long Setup()
2666 	{
2667 		m_program		 = 0;
2668 		m_storage_buffer = 0;
2669 		m_vertex_array   = 0;
2670 		m_vertex_buffer  = 0;
2671 		return NO_ERROR;
2672 	}
2673 
Run()2674 	virtual long Run()
2675 	{
2676 		if (!SupportedInVS(1))
2677 			return NOT_SUPPORTED;
2678 		if (!SupportedInGS(1))
2679 			return NOT_SUPPORTED;
2680 
2681 		const char* const glsl_vs =
2682 			NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2683 			   "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_vs_buffer;" NL "void main() {" NL
2684 			   "  gl_Position = g_in_position;" NL "  atomicAdd(g_vs_buffer.u[0].x, g_vs_buffer.u[gl_VertexID][1]);" NL
2685 			   "  atomicAdd(g_vs_buffer.u[0][0], g_vs_buffer.u[gl_VertexID].z);" NL
2686 			   "  atomicAdd(g_vs_buffer.i[0].x, g_vs_buffer.i[gl_VertexID][1]);" NL
2687 			   "  atomicAdd(g_vs_buffer.i[0][0], g_vs_buffer.i[gl_VertexID].z);" NL "}";
2688 
2689 		const char* const glsl_gs = NL
2690 			"layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
2691 			"layout(std430, binding = 0) buffer Buffer {" NL "  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_gs_buffer;" NL
2692 			"void main() {" NL "  gl_Position = gl_in[0].gl_Position;" NL "  gl_PrimitiveID = gl_PrimitiveIDIn;" NL
2693 			"  EmitVertex();" NL "  atomicAdd(g_gs_buffer.u[0].x, g_gs_buffer.u[gl_PrimitiveIDIn][1]);" NL
2694 			"  atomicAdd(g_gs_buffer.i[0].x, g_gs_buffer.i[gl_PrimitiveIDIn][1]);" NL "}";
2695 
2696 		const char* const glsl_fs = NL
2697 			"layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Buffer {" NL
2698 			"  uvec4 u[4];" NL "  ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2699 			"  g_fs_out = vec4(0, 1, 0, 1);" NL "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_PrimitiveID][1]);" NL
2700 			"  atomicAdd(g_fs_buffer.i[0].x, g_fs_buffer.i[gl_PrimitiveID][1]);" NL "}";
2701 
2702 		m_program = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
2703 		glLinkProgram(m_program);
2704 		if (!CheckProgram(m_program))
2705 			return ERROR;
2706 
2707 		/* init storage buffer */
2708 		{
2709 			glGenBuffers(1, &m_storage_buffer);
2710 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2711 			glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2712 			ivec4* ptr = reinterpret_cast<ivec4*>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2713 			if (!ptr)
2714 				return ERROR;
2715 			for (int i = 0; i < 4; ++i)
2716 			{
2717 				ptr[i * 2]	 = ivec4(0, 1, 2, 0);
2718 				ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2719 			}
2720 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2721 		}
2722 
2723 		/* init vertex buffer */
2724 		{
2725 			const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2726 			glGenBuffers(1, &m_vertex_buffer);
2727 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2728 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2729 			glBindBuffer(GL_ARRAY_BUFFER, 0);
2730 		}
2731 
2732 		glGenVertexArrays(1, &m_vertex_array);
2733 		glBindVertexArray(m_vertex_array);
2734 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2735 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2736 		glBindBuffer(GL_ARRAY_BUFFER, 0);
2737 		glEnableVertexAttribArray(0);
2738 		glBindVertexArray(0);
2739 
2740 		glClear(GL_COLOR_BUFFER_BIT);
2741 		glUseProgram(m_program);
2742 		glBindVertexArray(m_vertex_array);
2743 		glDrawArrays(GL_POINTS, 0, 4);
2744 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2745 
2746 		GLuint u;
2747 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &u);
2748 		if (u != 20)
2749 		{
2750 			m_context.getTestContext().getLog()
2751 				<< tcu::TestLog::Message << "Data at offset 0 is " << u << " should be 20." << tcu::TestLog::EndMessage;
2752 			return ERROR;
2753 		}
2754 		GLint i;
2755 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(GLuint) * 4, 4, &i);
2756 		if (i != 20)
2757 		{
2758 			m_context.getTestContext().getLog()
2759 				<< tcu::TestLog::Message << "Data at offset 0 is " << i << " should be 20." << tcu::TestLog::EndMessage;
2760 			return ERROR;
2761 		}
2762 
2763 		return NO_ERROR;
2764 	}
2765 
Cleanup()2766 	virtual long Cleanup()
2767 	{
2768 		glUseProgram(0);
2769 		glDeleteProgram(m_program);
2770 		glDeleteBuffers(1, &m_storage_buffer);
2771 		glDeleteBuffers(1, &m_vertex_buffer);
2772 		glDeleteVertexArrays(1, &m_vertex_array);
2773 		return NO_ERROR;
2774 	}
2775 };
2776 
2777 class BasicAtomicCase3CS : public ShaderStorageBufferObjectBase
2778 {
2779 	GLuint m_program;
2780 	GLuint m_storage_buffer;
2781 
Setup()2782 	virtual long Setup()
2783 	{
2784 		m_program		 = 0;
2785 		m_storage_buffer = 0;
2786 		return NO_ERROR;
2787 	}
2788 
Run()2789 	virtual long Run()
2790 	{
2791 		const char* const glsl_cs =
2792 			NL "layout(local_size_y = 4) in;" NL "layout(std430) coherent buffer Buffer {" NL "  uvec4 u[4];" NL
2793 			   "  ivec3 i[4];" NL "} g_fs_buffer;" NL "void main() {" NL
2794 			   "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y][2]);" NL
2795 			   "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y][1]);" NL
2796 			   "  atomicAdd(g_fs_buffer.u[0].x, g_fs_buffer.u[gl_LocalInvocationID.y].z);" NL
2797 			   "  atomicAdd(g_fs_buffer.i[0].x, 2 * g_fs_buffer.i[gl_LocalInvocationID.y].y);" NL "}";
2798 		m_program = CreateProgramCS(glsl_cs);
2799 		glLinkProgram(m_program);
2800 		if (!CheckProgram(m_program))
2801 			return ERROR;
2802 
2803 		/* init storage buffer */
2804 		{
2805 			glGenBuffers(1, &m_storage_buffer);
2806 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
2807 			glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * sizeof(int) * 4, NULL, GL_DYNAMIC_DRAW);
2808 			ivec4* ptr = reinterpret_cast<ivec4*>(
2809 				glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8 * sizeof(int) * 4, GL_MAP_WRITE_BIT));
2810 			if (!ptr)
2811 				return ERROR;
2812 			for (int i = 0; i < 4; ++i)
2813 			{
2814 				ptr[i * 2]	 = ivec4(0, 1, 2, 0);
2815 				ptr[i * 2 + 1] = ivec4(0, 1, 2, 0);
2816 			}
2817 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2818 		}
2819 
2820 		glUseProgram(m_program);
2821 		glDispatchCompute(1, 1, 1);
2822 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2823 
2824 		GLuint* u = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
2825 		if (!u)
2826 			return ERROR;
2827 		if (*u != 16)
2828 		{
2829 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *u
2830 												<< " should be 16." << tcu::TestLog::EndMessage;
2831 			return ERROR;
2832 		}
2833 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2834 		GLint* i = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64, 4, GL_MAP_READ_BIT);
2835 		if (!i)
2836 			return ERROR;
2837 		if (*i != 16)
2838 		{
2839 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Data at offset 0 is " << *i
2840 												<< " should be 16." << tcu::TestLog::EndMessage;
2841 			return ERROR;
2842 		}
2843 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2844 
2845 		return NO_ERROR;
2846 	}
2847 
Cleanup()2848 	virtual long Cleanup()
2849 	{
2850 		glUseProgram(0);
2851 		glDeleteProgram(m_program);
2852 		glDeleteBuffers(1, &m_storage_buffer);
2853 		return NO_ERROR;
2854 	}
2855 };
2856 //-----------------------------------------------------------------------------
2857 // 1.8.4 BasicAtomicCase4
2858 //-----------------------------------------------------------------------------
2859 
2860 class BasicAtomicCase4 : public ShaderStorageBufferObjectBase
2861 {
2862 	GLuint m_program;
2863 	GLuint m_storage_buffer[2];
2864 	GLuint m_vertex_array;
2865 	GLuint m_vertex_buffer;
2866 
Setup()2867 	virtual long Setup()
2868 	{
2869 		m_program = 0;
2870 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2871 		m_vertex_array  = 0;
2872 		m_vertex_buffer = 0;
2873 		return NO_ERROR;
2874 	}
2875 
Run()2876 	virtual long Run()
2877 	{
2878 		if (!SupportedInVS(2))
2879 			return NOT_SUPPORTED;
2880 
2881 		const char* const glsl_vs =
2882 			NL "layout(location = 0) in vec4 g_in_position;" NL "layout(std430, binding = 0) buffer Counters {" NL
2883 			   "  uint g_uint_counter;" NL "  int g_int_counter;" NL "};" NL
2884 			   "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL "  int idata[8];" NL
2885 			   "} g_output;" NL "void main() {" NL "  gl_Position = g_in_position;" NL
2886 			   "  const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2887 			   "  const int iidx = atomicAdd(g_int_counter, -1);" NL "  g_output.udata[uidx] = uidx;" NL
2888 			   "  g_output.idata[iidx] = iidx;" NL "}";
2889 
2890 		const char* const glsl_fs =
2891 			NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(std430, binding = 0) buffer Counters {" NL
2892 			   "  uint g_uint_counter;" NL "  int g_int_counter;" NL "};" NL
2893 			   "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL "  int idata[8];" NL
2894 			   "} g_output;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL
2895 			   "  const uint uidx = atomicAdd(g_uint_counter, 1u);" NL
2896 			   "  const int iidx = atomicAdd(g_int_counter, -1);" NL "  g_output.udata[uidx] = uidx;" NL
2897 			   "  g_output.idata[iidx] = iidx;" NL "}";
2898 		m_program = CreateProgram(glsl_vs, glsl_fs);
2899 		glLinkProgram(m_program);
2900 		if (!CheckProgram(m_program))
2901 			return ERROR;
2902 
2903 		glGenBuffers(2, m_storage_buffer);
2904 		/* counter buffer */
2905 		{
2906 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
2907 			glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2908 			int* ptr = reinterpret_cast<int*>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
2909 			if (!ptr)
2910 				return ERROR;
2911 			*ptr++ = 0;
2912 			*ptr++ = 7;
2913 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2914 		}
2915 		/* output buffer */
2916 		{
2917 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
2918 			glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
2919 		}
2920 		/* vertex buffer */
2921 		{
2922 			const float data[] = { -0.8f, -0.8f, 0.8f, -0.8f, -0.8f, 0.8f, 0.8f, 0.8f };
2923 			glGenBuffers(1, &m_vertex_buffer);
2924 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2925 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
2926 			glBindBuffer(GL_ARRAY_BUFFER, 0);
2927 		}
2928 
2929 		glGenVertexArrays(1, &m_vertex_array);
2930 		glBindVertexArray(m_vertex_array);
2931 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
2932 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
2933 		glBindBuffer(GL_ARRAY_BUFFER, 0);
2934 		glEnableVertexAttribArray(0);
2935 		glBindVertexArray(0);
2936 
2937 		glClear(GL_COLOR_BUFFER_BIT);
2938 		glUseProgram(m_program);
2939 		glBindVertexArray(m_vertex_array);
2940 		glDrawArrays(GL_POINTS, 0, 4);
2941 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2942 
2943 		GLuint udata[8];
2944 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(udata), udata);
2945 		for (GLuint i = 0; i < 8; ++i)
2946 		{
2947 			if (udata[i] != i)
2948 			{
2949 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
2950 													<< udata[i] << " should be " << i << tcu::TestLog::EndMessage;
2951 				return ERROR;
2952 			}
2953 		}
2954 		GLint idata[8];
2955 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, sizeof(udata), sizeof(idata), idata);
2956 		for (GLint i = 0; i < 8; ++i)
2957 		{
2958 			if (idata[i] != i)
2959 			{
2960 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
2961 													<< idata[i] << " should be " << i << tcu::TestLog::EndMessage;
2962 				return ERROR;
2963 			}
2964 		}
2965 		return NO_ERROR;
2966 	}
2967 
Cleanup()2968 	virtual long Cleanup()
2969 	{
2970 		glUseProgram(0);
2971 		glDeleteProgram(m_program);
2972 		glDeleteBuffers(2, m_storage_buffer);
2973 		glDeleteBuffers(1, &m_vertex_buffer);
2974 		glDeleteVertexArrays(1, &m_vertex_array);
2975 		return NO_ERROR;
2976 	}
2977 };
2978 
2979 class BasicAtomicCase4CS : public ShaderStorageBufferObjectBase
2980 {
2981 	GLuint m_program;
2982 	GLuint m_storage_buffer[2];
2983 
Setup()2984 	virtual long Setup()
2985 	{
2986 		m_program = 0;
2987 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
2988 		return NO_ERROR;
2989 	}
2990 
Run()2991 	virtual long Run()
2992 	{
2993 		const char* const glsl_cs =
2994 			NL "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;" NL
2995 			   "layout(std430, binding = 0) coherent buffer Counters {" NL "  uint g_uint_counter;" NL
2996 			   "  int g_int_counter;" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL "  uint udata[8];" NL
2997 			   "  int idata[8];" NL "} g_output;" NL "void main() {" NL
2998 			   "  uint uidx = atomicAdd(g_uint_counter, 1u);" NL "  int iidx = atomicAdd(g_int_counter, -1);" NL
2999 			   "  g_output.udata[uidx] = uidx;" NL "  g_output.idata[iidx] = iidx;" NL "}";
3000 		m_program = CreateProgramCS(glsl_cs);
3001 		glLinkProgram(m_program);
3002 		if (!CheckProgram(m_program))
3003 			return ERROR;
3004 
3005 		glGenBuffers(2, m_storage_buffer);
3006 		/* counter buffer */
3007 		{
3008 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
3009 			glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3010 			int* ptr = reinterpret_cast<int*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_WRITE_BIT));
3011 			if (!ptr)
3012 				return ERROR;
3013 			*ptr++ = 0;
3014 			*ptr++ = 7;
3015 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3016 		}
3017 		/* output buffer */
3018 		{
3019 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
3020 			glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * sizeof(int), NULL, GL_DYNAMIC_DRAW);
3021 		}
3022 		glUseProgram(m_program);
3023 		glDispatchCompute(1, 1, 1);
3024 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3025 
3026 		GLuint* udata = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 32, GL_MAP_READ_BIT);
3027 		if (!udata)
3028 			return ERROR;
3029 		for (GLuint i = 0; i < 8; ++i)
3030 		{
3031 			if (udata[i] != i)
3032 			{
3033 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "uData at index " << i << " is "
3034 													<< udata[i] << " should be " << i << tcu::TestLog::EndMessage;
3035 				return ERROR;
3036 			}
3037 		}
3038 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3039 		GLint* idata = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 32, 32, GL_MAP_READ_BIT);
3040 		if (!idata)
3041 			return ERROR;
3042 		for (GLint i = 0; i < 8; ++i)
3043 		{
3044 			if (idata[i] != i)
3045 			{
3046 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "iData at index " << i << " is "
3047 													<< idata[i] << " should be " << i << tcu::TestLog::EndMessage;
3048 				return ERROR;
3049 			}
3050 		}
3051 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3052 		return NO_ERROR;
3053 	}
3054 
Cleanup()3055 	virtual long Cleanup()
3056 	{
3057 		glUseProgram(0);
3058 		glDeleteProgram(m_program);
3059 		glDeleteBuffers(2, m_storage_buffer);
3060 		return NO_ERROR;
3061 	}
3062 };
3063 //-----------------------------------------------------------------------------
3064 // 1.9.x BasicStdLayoutBase2
3065 //-----------------------------------------------------------------------------
3066 
3067 class BasicStdLayoutBase2VS : public ShaderStorageBufferObjectBase
3068 {
3069 	GLuint m_program;
3070 	GLuint m_buffer[8];
3071 	GLuint m_vertex_array;
3072 
3073 	virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
3074 
Setup()3075 	virtual long Setup()
3076 	{
3077 		m_program = 0;
3078 		memset(m_buffer, 0, sizeof(m_buffer));
3079 		m_vertex_array = 0;
3080 		return NO_ERROR;
3081 	}
3082 
Run()3083 	virtual long Run()
3084 	{
3085 		if (!SupportedInVS(8))
3086 			return NOT_SUPPORTED;
3087 		std::vector<GLubyte> in_data[4];
3088 		const char*			 glsl_vs = GetInput(in_data);
3089 
3090 		m_program = CreateProgram(glsl_vs, "");
3091 		glLinkProgram(m_program);
3092 		if (!CheckProgram(m_program))
3093 			return ERROR;
3094 
3095 		glGenBuffers(8, m_buffer);
3096 
3097 		for (GLuint i = 0; i < 4; ++i)
3098 		{
3099 			// input buffers
3100 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3101 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3102 
3103 			// output buffers
3104 			std::vector<GLubyte> out_data(in_data[i].size());
3105 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3106 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3107 		}
3108 
3109 		glGenVertexArrays(1, &m_vertex_array);
3110 		glEnable(GL_RASTERIZER_DISCARD);
3111 
3112 		glUseProgram(m_program);
3113 		glBindVertexArray(m_vertex_array);
3114 		glDrawArrays(GL_POINTS, 0, 1);
3115 
3116 		bool status = true;
3117 		for (int j = 0; j < 4; ++j)
3118 		{
3119 			std::vector<GLubyte> out_data(in_data[j].size());
3120 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3121 			glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3122 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
3123 
3124 			for (size_t i = 0; i < in_data[j].size(); ++i)
3125 			{
3126 				if (in_data[j][i] != out_data[i])
3127 				{
3128 					m_context.getTestContext().getLog()
3129 						<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3130 						<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3131 						<< tcu::TestLog::EndMessage;
3132 					status = false;
3133 				}
3134 			}
3135 		}
3136 		if (!status)
3137 			return ERROR;
3138 		return NO_ERROR;
3139 	}
3140 
Cleanup()3141 	virtual long Cleanup()
3142 	{
3143 		glDisable(GL_RASTERIZER_DISCARD);
3144 		glUseProgram(0);
3145 		glDeleteProgram(m_program);
3146 		glDeleteBuffers(8, m_buffer);
3147 		glDeleteVertexArrays(1, &m_vertex_array);
3148 		return NO_ERROR;
3149 	}
3150 };
3151 
3152 class BasicStdLayoutBase2CS : public ShaderStorageBufferObjectBase
3153 {
3154 	GLuint m_program;
3155 	GLuint m_buffer[8];
3156 
3157 	virtual const char* GetInput(std::vector<GLubyte> in_data[4]) = 0;
3158 
Setup()3159 	virtual long Setup()
3160 	{
3161 		m_program = 0;
3162 		memset(m_buffer, 0, sizeof(m_buffer));
3163 		return NO_ERROR;
3164 	}
3165 
Run()3166 	virtual long Run()
3167 	{
3168 		std::vector<GLubyte> in_data[4];
3169 		std::stringstream	ss;
3170 		GLint				 blocksCS;
3171 		glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksCS);
3172 		if (blocksCS < 8)
3173 			return NO_ERROR;
3174 		ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
3175 		m_program = CreateProgramCS(ss.str());
3176 		glLinkProgram(m_program);
3177 		if (!CheckProgram(m_program))
3178 			return ERROR;
3179 
3180 		glGenBuffers(8, m_buffer);
3181 
3182 		for (GLuint i = 0; i < 4; ++i)
3183 		{
3184 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_buffer[i]);
3185 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &in_data[i][0], GL_STATIC_DRAW);
3186 
3187 			std::vector<GLubyte> out_data(in_data[i].size());
3188 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_buffer[i + 4]);
3189 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[i].size(), &out_data[0], GL_STATIC_DRAW);
3190 		}
3191 
3192 		glUseProgram(m_program);
3193 		glDispatchCompute(1, 1, 1);
3194 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3195 
3196 		bool status = true;
3197 		for (int j = 0; j < 4; ++j)
3198 		{
3199 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 4]);
3200 			GLubyte* out_data =
3201 				(GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
3202 			if (!out_data)
3203 				return ERROR;
3204 
3205 			for (size_t i = 0; i < in_data[j].size(); ++i)
3206 			{
3207 				if (in_data[j][i] != out_data[i])
3208 				{
3209 					m_context.getTestContext().getLog()
3210 						<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
3211 						<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
3212 						<< tcu::TestLog::EndMessage;
3213 					status = false;
3214 				}
3215 			}
3216 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3217 		}
3218 		if (!status)
3219 			return ERROR;
3220 		return NO_ERROR;
3221 	}
3222 
Cleanup()3223 	virtual long Cleanup()
3224 	{
3225 		glUseProgram(0);
3226 		glDeleteProgram(m_program);
3227 		glDeleteBuffers(8, m_buffer);
3228 		return NO_ERROR;
3229 	}
3230 };
3231 //-----------------------------------------------------------------------------
3232 // 1.9.1 BasicStdLayoutCase1
3233 //-----------------------------------------------------------------------------
GetInputC1(std::vector<GLubyte> in_data[4])3234 const char* GetInputC1(std::vector<GLubyte> in_data[4])
3235 {
3236 	for (int i = 0; i < 4; ++i)
3237 	{
3238 		in_data[i].resize(1 * 4);
3239 		float* fp = reinterpret_cast<float*>(&in_data[i][0]);
3240 		fp[0]	 = static_cast<float>(i + 1) * 1.0f;
3241 	}
3242 
3243 	return NL "layout(std430, binding = 0) buffer Input {" NL "  float data0;" NL "} g_input[4];" NL
3244 			  "layout(std430, binding = 4) buffer Output {" NL "  float data0;" NL "} g_output[4];" NL
3245 			  "void main() {" NL "  for (int i = 0; i < 4; ++i) {" NL "    g_output[i].data0 = g_input[i].data0;" NL
3246 			  "  }" NL "}";
3247 }
3248 
3249 class BasicStdLayoutCase1VS : public BasicStdLayoutBase2VS
3250 {
GetInput(std::vector<GLubyte> in_data[4])3251 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3252 	{
3253 		return GetInputC1(in_data);
3254 	}
3255 };
3256 
3257 class BasicStdLayoutCase1CS : public BasicStdLayoutBase2CS
3258 {
GetInput(std::vector<GLubyte> in_data[4])3259 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3260 	{
3261 		return GetInputC1(in_data);
3262 	}
3263 };
3264 
3265 //-----------------------------------------------------------------------------
3266 // 1.9.2 BasicStdLayoutCase2
3267 //-----------------------------------------------------------------------------
GetInputC2(std::vector<GLubyte> in_data[4])3268 const char* GetInputC2(std::vector<GLubyte> in_data[4])
3269 {
3270 	/* input 0, std140 */
3271 	{
3272 		in_data[0].resize(12 * 4);
3273 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3274 		fp[0]	 = 1.0f;
3275 		fp[1]	 = 0.0f;
3276 		fp[2]	 = 0.0f;
3277 		fp[3]	 = 0.0f;
3278 		fp[4]	 = 2.0f;
3279 		fp[5]	 = 0.0f;
3280 		fp[6]	 = 0.0f;
3281 		fp[7]	 = 0.0f;
3282 		fp[8]	 = 3.0f;
3283 		fp[9]	 = 0.0f;
3284 		fp[10]	= 0.0f;
3285 		fp[11]	= 0.0f;
3286 	}
3287 	/* input 1, std430 */
3288 	{
3289 		in_data[1].resize(3 * 4);
3290 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3291 		fp[0]	 = 4.0f;
3292 		fp[1]	 = 5.0f;
3293 		fp[2]	 = 6.0f;
3294 	}
3295 	/* input 2, std140 */
3296 	{
3297 		in_data[2].resize(12 * 4);
3298 		float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3299 		fp[0]	 = 7.0f;
3300 		fp[1]	 = 0.0f;
3301 		fp[2]	 = 0.0f;
3302 		fp[3]	 = 0.0f;
3303 		fp[4]	 = 8.0f;
3304 		fp[5]	 = 0.0f;
3305 		fp[6]	 = 0.0f;
3306 		fp[7]	 = 0.0f;
3307 		fp[8]	 = 9.0f;
3308 		fp[9]	 = 0.0f;
3309 		fp[10]	= 0.0f;
3310 		fp[11]	= 0.0f;
3311 	}
3312 	/* input 3, std430 */
3313 	{
3314 		in_data[3].resize(3 * 4);
3315 		float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3316 		fp[0]	 = 10.0f;
3317 		fp[1]	 = 11.0f;
3318 		fp[2]	 = 12.0f;
3319 	}
3320 	return NL "layout(std140, binding = 0) buffer Input0 {" NL "  float data0[3];" NL "} g_input0;" NL
3321 			  "layout(std430, binding = 1) buffer Input1 {" NL "  float data0[3];" NL "} g_input1;" NL
3322 			  "layout(std140, binding = 2) buffer Input2 {" NL "  float data0[3];" NL "} g_input2;" NL
3323 			  "layout(std430, binding = 3) buffer Input3 {" NL "  float data0[3];" NL "} g_input3;" NL
3324 			  "layout(std140, binding = 4) buffer Output0 {" NL "  float data0[3];" NL "} g_output0;" NL
3325 			  "layout(std430, binding = 5) buffer Output1 {" NL "  float data0[3];" NL "} g_output1;" NL
3326 			  "layout(std140, binding = 6) buffer Output2 {" NL "  float data0[3];" NL "} g_output2;" NL
3327 			  "layout(std430, binding = 7) buffer Output3 {" NL "  float data0[3];" NL "} g_output3;" NL
3328 			  "void main() {" NL
3329 			  "  for (int i = 0; i < g_input0.data0.length(); ++i) g_output0.data0[i] = g_input0.data0[i];" NL
3330 			  "  for (int i = 0; i < g_input1.data0.length(); ++i) g_output1.data0[i] = g_input1.data0[i];" NL
3331 			  "  for (int i = 0; i < g_input2.data0.length(); ++i) g_output2.data0[i] = g_input2.data0[i];" NL
3332 			  "  for (int i = 0; i < g_input3.data0.length(); ++i) g_output3.data0[i] = g_input3.data0[i];" NL "}";
3333 }
3334 
3335 class BasicStdLayoutCase2VS : public BasicStdLayoutBase2VS
3336 {
GetInput(std::vector<GLubyte> in_data[4])3337 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3338 	{
3339 		return GetInputC2(in_data);
3340 	}
3341 };
3342 
3343 class BasicStdLayoutCase2CS : public BasicStdLayoutBase2CS
3344 {
GetInput(std::vector<GLubyte> in_data[4])3345 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3346 	{
3347 		return GetInputC2(in_data);
3348 	}
3349 };
3350 
3351 //-----------------------------------------------------------------------------
3352 // 1.9.3 BasicStdLayoutCase3
3353 //-----------------------------------------------------------------------------
GetInputC3(std::vector<GLubyte> in_data[4])3354 const char* GetInputC3(std::vector<GLubyte> in_data[4])
3355 {
3356 	/* input 0, std140 */
3357 	{
3358 		in_data[0].resize(62 * 4);
3359 		float* fp							= reinterpret_cast<float*>(&in_data[0][0]);
3360 		int*   ip							= reinterpret_cast<int*>(&in_data[0][0]);
3361 		ip[0]								= 1;
3362 		ip[1]								= 0;
3363 		ip[2]								= 0;
3364 		ip[3]								= 0;
3365 		fp[4]								= 2.0f;
3366 		fp[5]								= 0.0f;
3367 		fp[6]								= 0.0f;
3368 		fp[7]								= 0.0f;
3369 		fp[8]								= 3.0f;
3370 		fp[9]								= 0.0f;
3371 		fp[10]								= 0.0f;
3372 		fp[11]								= 0.0f;
3373 		fp[12]								= 4.0f;
3374 		fp[13]								= 0.0f;
3375 		fp[14]								= 0.0f;
3376 		fp[15]								= 0.0f;
3377 		fp[16]								= 5.0f;
3378 		fp[17]								= 0.0f;
3379 		fp[18]								= 0.0f;
3380 		fp[19]								= 0.0f;
3381 		fp[20]								= 6.0f;
3382 		fp[21]								= 0.0f;
3383 		fp[22]								= 0.0f;
3384 		fp[23]								= 0.0f;
3385 		fp[24]								= 7.0f;
3386 		fp[25]								= 8.0f;
3387 		fp[26]								= 0.0f;
3388 		fp[27]								= 0.0f;
3389 		fp[28]								= 9.0f;
3390 		fp[29]								= 10.0f;
3391 		fp[30]								= 0.0f;
3392 		fp[31]								= 0.0f;
3393 		fp[32]								= 11.0f;
3394 		fp[33]								= 12.0f;
3395 		fp[34]								= 0.0f;
3396 		fp[35]								= 0.0f;
3397 		*reinterpret_cast<double*>(fp + 36) = 13.0;
3398 		*reinterpret_cast<double*>(fp + 38) = 0.0;
3399 		*reinterpret_cast<double*>(fp + 40) = 14.0;
3400 		*reinterpret_cast<double*>(fp + 42) = 0.0;
3401 		*reinterpret_cast<double*>(fp + 44) = 15.0;
3402 		*reinterpret_cast<double*>(fp + 46) = 0.0;
3403 		ip[48]								= 16;
3404 		ip[49]								= 0;
3405 		ip[50]								= 0;
3406 		ip[51]								= 0;
3407 		ip[52]								= 0;
3408 		ip[53]								= 0;
3409 		ip[54]								= 0;
3410 		ip[55]								= 0;
3411 		*reinterpret_cast<double*>(fp + 56) = 17.0;
3412 		*reinterpret_cast<double*>(fp + 58) = 18.0;
3413 		*reinterpret_cast<double*>(fp + 60) = 19.0;
3414 	}
3415 	/* input 1, std430 */
3416 	{
3417 		in_data[1].resize(32 * 4);
3418 		float* fp							= reinterpret_cast<float*>(&in_data[1][0]);
3419 		int*   ip							= reinterpret_cast<int*>(&in_data[1][0]);
3420 		ip[0]								= 1;
3421 		fp[1]								= 2.0f;
3422 		fp[2]								= 3.0f;
3423 		fp[3]								= 4.0f;
3424 		fp[4]								= 5.0f;
3425 		fp[5]								= 6.0f;
3426 		fp[6]								= 7.0f;
3427 		fp[7]								= 8.0f;
3428 		fp[8]								= 9.0f;
3429 		fp[9]								= 10.0f;
3430 		fp[10]								= 11.0f;
3431 		fp[11]								= 12.0f;
3432 		*reinterpret_cast<double*>(fp + 12) = 13.0;
3433 		*reinterpret_cast<double*>(fp + 14) = 14.0;
3434 		*reinterpret_cast<double*>(fp + 16) = 15.0;
3435 		ip[18]								= 16;
3436 		ip[19]								= 0;
3437 		*reinterpret_cast<double*>(fp + 20) = 0.0;
3438 		*reinterpret_cast<double*>(fp + 22) = 0.0;
3439 		*reinterpret_cast<double*>(fp + 24) = 17.0;
3440 		*reinterpret_cast<double*>(fp + 26) = 18.0;
3441 		*reinterpret_cast<double*>(fp + 28) = 19.0;
3442 	}
3443 	/* input 2, std140 */
3444 	{
3445 		in_data[2].resize(5 * 4);
3446 		int* ip = reinterpret_cast<int*>(&in_data[2][0]);
3447 		ip[0]   = 1;
3448 		ip[1]   = 0;
3449 		ip[2]   = 0;
3450 		ip[3]   = 0;
3451 		ip[4]   = 2;
3452 	}
3453 	/* input 3, std430 */
3454 	{
3455 		in_data[3].resize(2 * 4);
3456 		int* ip = reinterpret_cast<int*>(&in_data[3][0]);
3457 		ip[0]   = 1;
3458 		ip[1]   = 2;
3459 	}
3460 	return NL "layout(std140, binding = 0) buffer Input0 {" NL "  int data0;" NL "  float data1[5];" NL
3461 			  "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3462 			  "} g_input0;" NL "layout(std430, binding = 1) buffer Input1 {" NL "  int data0;" NL "  float data1[5];" NL
3463 			  "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3464 			  "} g_input1;" NL "struct Struct0 {" NL "  int data0;" NL "};" NL
3465 			  "layout(std140, binding = 2) buffer Input2 {" NL "  int data0;" NL "  Struct0 data1;" NL "} g_input2;" NL
3466 			  "layout(std430, binding = 3) buffer Input3 {" NL "  int data0;" NL "  Struct0 data1;" NL "} g_input3;"
3467 
3468 		NL "layout(std140, binding = 4) buffer Output0 {" NL "  int data0;" NL "  float data1[5];" NL
3469 			  "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL "  dvec3 data6;" NL
3470 			  "} g_output0;" NL "layout(std430, binding = 5) buffer Output1 {" NL "  int data0;" NL
3471 			  "  float data1[5];" NL "  mat3x2 data2;" NL "  double data3;" NL "  double data4[2];" NL "  int data5;" NL
3472 			  "  dvec3 data6;" NL "} g_output1;" NL "layout(std140, binding = 6) buffer Output2 {" NL "  int data0;" NL
3473 			  "  Struct0 data1;" NL "} g_output2;" NL "layout(std430, binding = 7) buffer Output3 {" NL
3474 			  "  int data0;" NL "  Struct0 data1;" NL "} g_output3;" NL "void main() {" NL
3475 			  "  g_output0.data0 = g_input0.data0;" NL
3476 			  "  for (int i = 0; i < g_input0.data1.length(); ++i) g_output0.data1[i] = g_input0.data1[i];" NL
3477 			  "  g_output0.data2 = g_input0.data2;" NL "  g_output0.data3 = g_input0.data3;" NL
3478 			  "  for (int i = 0; i < g_input0.data4.length(); ++i) g_output0.data4[i] = g_input0.data4[i];" NL
3479 			  "  g_output0.data5 = g_input0.data5;" NL "  g_output0.data6 = g_input0.data6;"
3480 
3481 		NL "  g_output1.data0 = g_input1.data0;" NL
3482 			  "  for (int i = 0; i < g_input1.data1.length(); ++i) g_output1.data1[i] = g_input1.data1[i];" NL
3483 			  "  g_output1.data2 = g_input1.data2;" NL "  g_output1.data3 = g_input1.data3;" NL
3484 			  "  for (int i = 0; i < g_input1.data4.length(); ++i) g_output1.data4[i] = g_input1.data4[i];" NL
3485 			  "  g_output1.data5 = g_input1.data5;" NL "  g_output1.data6 = g_input1.data6;"
3486 
3487 		NL "  g_output2.data0 = g_input2.data0;" NL "  g_output2.data1 = g_input2.data1;"
3488 
3489 		NL "  g_output3.data0 = g_input3.data0;" NL "  g_output3.data1 = g_input3.data1;" NL "}";
3490 }
3491 
3492 class BasicStdLayoutCase3VS : public BasicStdLayoutBase2VS
3493 {
GetInput(std::vector<GLubyte> in_data[4])3494 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3495 	{
3496 		return GetInputC3(in_data);
3497 	}
3498 };
3499 
3500 class BasicStdLayoutCase3CS : public BasicStdLayoutBase2CS
3501 {
GetInput(std::vector<GLubyte> in_data[4])3502 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3503 	{
3504 		return GetInputC3(in_data);
3505 	}
3506 };
3507 
3508 //-----------------------------------------------------------------------------
3509 // 1.9.4 BasicStdLayoutCase4
3510 //-----------------------------------------------------------------------------
GetInputC4(std::vector<GLubyte> in_data[4])3511 const char* GetInputC4(std::vector<GLubyte> in_data[4])
3512 {
3513 	/* input 0, std140 */
3514 	{
3515 		in_data[0].resize(60 * 4);
3516 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
3517 		int*   ip = reinterpret_cast<int*>(&in_data[0][0]);
3518 		ip[0]	 = 1;
3519 		ip[1]	 = 0;
3520 		ip[2]	 = 0;
3521 		ip[3]	 = 0;
3522 		ip[4]	 = 2;
3523 		ip[5]	 = 3;
3524 		ip[6]	 = 0;
3525 		ip[7]	 = 0;
3526 		ip[8]	 = 4;
3527 		ip[9]	 = 5;
3528 		ip[10]	= 0;
3529 		ip[11]	= 0;
3530 		fp[12]	= 6.0f;
3531 		fp[13]	= 0.0f;
3532 		fp[14]	= 0.0f;
3533 		fp[15]	= 0.0f;
3534 		fp[16]	= 7.0f;
3535 		fp[17]	= 8.0f;
3536 		fp[18]	= 0.0f;
3537 		fp[19]	= 0.0f;
3538 		ip[20]	= 9;
3539 		ip[21]	= 10;
3540 		ip[22]	= 11;
3541 		ip[23]	= 0;
3542 		fp[24]	= 12.0f;
3543 		fp[25]	= 13.0f;
3544 		fp[26]	= 0.0f;
3545 		fp[27]	= 0.0f;
3546 		ip[28]	= 14;
3547 		ip[29]	= 15;
3548 		ip[30]	= 16;
3549 		ip[31]	= 0;
3550 		fp[32]	= 17.0f;
3551 		fp[33]	= 0.0f;
3552 		fp[34]	= 0.0f;
3553 		fp[35]	= 0.0f;
3554 		ip[36]	= 18;
3555 		ip[37]	= 0;
3556 		ip[38]	= 0;
3557 		ip[39]	= 0;
3558 		ip[40]	= 19;
3559 		ip[41]	= 20;
3560 		ip[42]	= 0;
3561 		ip[43]	= 0;
3562 		ip[44]	= 21;
3563 		ip[45]	= 0;
3564 		ip[45]	= 0;
3565 		ip[45]	= 0;
3566 		fp[48]	= 22.0f;
3567 		fp[49]	= 23.0f;
3568 		fp[50]	= 0.0f;
3569 		fp[51]	= 0.0f;
3570 		ip[52]	= 24;
3571 		ip[53]	= 25;
3572 		ip[54]	= 26;
3573 		ip[55]	= 0;
3574 		fp[56]	= 27.0f;
3575 	}
3576 	/* input 1, std140 */
3577 	{
3578 		in_data[1].resize(60 * 4);
3579 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
3580 		int*   ip = reinterpret_cast<int*>(&in_data[1][0]);
3581 		ip[0]	 = 101;
3582 		ip[1]	 = 0;
3583 		ip[2]	 = 0;
3584 		ip[3]	 = 0;
3585 		ip[4]	 = 102;
3586 		ip[5]	 = 103;
3587 		ip[6]	 = 0;
3588 		ip[7]	 = 0;
3589 		ip[8]	 = 104;
3590 		ip[9]	 = 105;
3591 		ip[10]	= 0;
3592 		ip[11]	= 0;
3593 		fp[12]	= 106.0f;
3594 		fp[13]	= 0.0f;
3595 		fp[14]	= 0.0f;
3596 		fp[15]	= 0.0f;
3597 		fp[16]	= 107.0f;
3598 		fp[17]	= 108.0f;
3599 		fp[18]	= 0.0f;
3600 		fp[19]	= 0.0f;
3601 		ip[20]	= 109;
3602 		ip[21]	= 110;
3603 		ip[22]	= 111;
3604 		ip[23]	= 0;
3605 		fp[24]	= 112.0f;
3606 		fp[25]	= 113.0f;
3607 		fp[26]	= 0.0f;
3608 		fp[27]	= 0.0f;
3609 		ip[28]	= 114;
3610 		ip[29]	= 115;
3611 		ip[30]	= 116;
3612 		ip[31]	= 0;
3613 		fp[32]	= 117.0f;
3614 		fp[33]	= 0.0f;
3615 		fp[34]	= 0.0f;
3616 		fp[35]	= 0.0f;
3617 		ip[36]	= 118;
3618 		ip[37]	= 0;
3619 		ip[38]	= 0;
3620 		ip[39]	= 0;
3621 		ip[40]	= 119;
3622 		ip[41]	= 120;
3623 		ip[42]	= 0;
3624 		ip[43]	= 0;
3625 		ip[44]	= 121;
3626 		ip[45]	= 0;
3627 		ip[45]	= 0;
3628 		ip[45]	= 0;
3629 		fp[48]	= 122.0f;
3630 		fp[49]	= 123.0f;
3631 		fp[50]	= 0.0f;
3632 		fp[51]	= 0.0f;
3633 		ip[52]	= 124;
3634 		ip[53]	= 125;
3635 		ip[54]	= 126;
3636 		ip[55]	= 0;
3637 		fp[56]	= 127.0f;
3638 	}
3639 	/* input 2, std430 */
3640 	{
3641 		in_data[2].resize(48 * 4);
3642 		float* fp = reinterpret_cast<float*>(&in_data[2][0]);
3643 		int*   ip = reinterpret_cast<int*>(&in_data[2][0]);
3644 		ip[0]	 = 1000;
3645 		ip[1]	 = 0;
3646 		ip[2]	 = 1001;
3647 		ip[3]	 = 1002;
3648 		ip[4]	 = 1003;
3649 		ip[5]	 = 1004;
3650 		fp[6]	 = 1005.0f;
3651 		fp[7]	 = 0.0f;
3652 		fp[8]	 = 1006.0f;
3653 		fp[9]	 = 1007.0f;
3654 		fp[10]	= 0.0f;
3655 		fp[11]	= 0.0f;
3656 		ip[12]	= 1008;
3657 		ip[13]	= 1009;
3658 		ip[14]	= 1010;
3659 		ip[15]	= 0;
3660 		fp[16]	= 1011.0f;
3661 		fp[17]	= 1012.0f;
3662 		fp[18]	= 0.0f;
3663 		fp[19]	= 0.0f;
3664 		ip[20]	= 1013;
3665 		ip[21]	= 1014;
3666 		ip[22]	= 1015;
3667 		ip[23]	= 0;
3668 		fp[24]	= 1016.0f;
3669 		fp[25]	= 0.0f;
3670 		fp[26]	= 0.0f;
3671 		fp[27]	= 0.0f;
3672 		ip[28]	= 1017;
3673 		ip[29]	= 0;
3674 		ip[30]	= 1018;
3675 		ip[31]	= 1019;
3676 		ip[32]	= 1020;
3677 		ip[33]	= 0;
3678 		ip[34]	= 0;
3679 		ip[35]	= 0;
3680 		fp[36]	= 1021.0f;
3681 		fp[37]	= 1022.0f;
3682 		fp[38]	= 0.0f;
3683 		fp[39]	= 0.0f;
3684 		ip[40]	= 1023;
3685 		ip[41]	= 1024;
3686 		ip[42]	= 1025;
3687 		ip[43]	= 0;
3688 		fp[44]	= 1026.0f;
3689 	}
3690 	/* input 3, std430 */
3691 	{
3692 		in_data[3].resize(48 * 4);
3693 		float* fp = reinterpret_cast<float*>(&in_data[3][0]);
3694 		int*   ip = reinterpret_cast<int*>(&in_data[3][0]);
3695 		ip[0]	 = 10000;
3696 		ip[1]	 = 0;
3697 		ip[2]	 = 10001;
3698 		ip[3]	 = 10002;
3699 		ip[4]	 = 10003;
3700 		ip[5]	 = 10004;
3701 		fp[6]	 = 10005.0f;
3702 		fp[7]	 = 0.0f;
3703 		fp[8]	 = 10006.0f;
3704 		fp[9]	 = 10007.0f;
3705 		fp[10]	= 0.0f;
3706 		fp[11]	= 0.0f;
3707 		ip[12]	= 10008;
3708 		ip[13]	= 10009;
3709 		ip[14]	= 10010;
3710 		ip[15]	= 0;
3711 		fp[16]	= 10011.0f;
3712 		fp[17]	= 10012.0f;
3713 		fp[18]	= 0.0f;
3714 		fp[19]	= 0.0f;
3715 		ip[20]	= 10013;
3716 		ip[21]	= 10014;
3717 		ip[22]	= 10015;
3718 		ip[23]	= 0;
3719 		fp[24]	= 10016.0f;
3720 		fp[25]	= 0.0f;
3721 		fp[26]	= 0.0f;
3722 		fp[27]	= 0.0f;
3723 		ip[28]	= 10017;
3724 		ip[29]	= 0;
3725 		ip[30]	= 10018;
3726 		ip[31]	= 10019;
3727 		ip[32]	= 10020;
3728 		ip[33]	= 0;
3729 		ip[34]	= 0;
3730 		ip[35]	= 0;
3731 		fp[36]	= 10021.0f;
3732 		fp[37]	= 10022.0f;
3733 		fp[38]	= 0.0f;
3734 		fp[39]	= 0.0f;
3735 		ip[40]	= 10023;
3736 		ip[41]	= 10024;
3737 		ip[42]	= 10025;
3738 		ip[43]	= 0;
3739 		fp[44]	= 10026.0f;
3740 	}
3741 	return NL
3742 		"struct Struct0 {" NL "  ivec2 data0;" NL "};" NL "struct Struct1 {" NL "  vec2 data0;" NL "  ivec3 data1;" NL
3743 		"};" NL "struct Struct2 {" NL "  int data0;" NL "  Struct0 data1;" NL "  int data2;" NL "  Struct1 data3;" NL
3744 		"  float data4;" NL "};" NL "layout(std140, binding = 0) buffer Input01 {" NL "  int data0;" NL
3745 		"  Struct0 data1[2];" NL "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL
3746 		"} g_input01[2];" NL "layout(std430, binding = 2) buffer Input23 {" NL "  int data0;" NL
3747 		"  Struct0 data1[2];" NL "  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL
3748 		"} g_input23[2];"
3749 
3750 		NL "layout(std140, binding = 4) buffer Output01 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3751 		"  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output01[2];" NL
3752 		"layout(std430, binding = 6) buffer Output23 {" NL "  int data0;" NL "  Struct0 data1[2];" NL
3753 		"  float data2;" NL "  Struct1 data3[2];" NL "  float data4;" NL "  Struct2 data5;" NL "} g_output23[2];" NL NL
3754 		"void main() {" NL "  for (int b = 0; b < g_input01.length(); ++b) {" NL
3755 		"    g_output01[b].data0 = g_input01[b].data0;" NL
3756 		"    for (int i = 0; i < g_input01[b].data1.length(); ++i) g_output01[b].data1[i] = g_input01[b].data1[i];" NL
3757 		"    g_output01[b].data2 = g_input01[b].data2;" NL "    g_output01[b].data3[0] = g_input01[b].data3[0];" NL
3758 		"    g_output01[b].data3[1] = g_input01[b].data3[1];" NL "    g_output01[b].data4 = g_input01[b].data4;" NL
3759 		"  }" NL "  g_output01[0].data5 = g_input01[0].data5;" NL "  g_output01[1].data5 = g_input01[1].data5;" NL NL
3760 		"  for (int b = 0; b < g_input23.length(); ++b) {" NL "    g_output23[b].data0 = g_input23[b].data0;" NL
3761 		"    for (int i = 0; i < g_input23[b].data1.length(); ++i) g_output23[b].data1[i] = g_input23[b].data1[i];" NL
3762 		"    g_output23[b].data2 = g_input23[b].data2;" NL "    g_output23[b].data3[0] = g_input23[b].data3[0];" NL
3763 		"    g_output23[b].data3[1] = g_input23[b].data3[1];" NL "    g_output23[b].data4 = g_input23[b].data4;" NL
3764 		"  }" NL "  g_output23[0].data5 = g_input23[0].data5;" NL "  g_output23[1].data5 = g_input23[1].data5;" NL "}";
3765 }
3766 
3767 class BasicStdLayoutCase4VS : public BasicStdLayoutBase2VS
3768 {
GetInput(std::vector<GLubyte> in_data[4])3769 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3770 	{
3771 		return GetInputC4(in_data);
3772 	}
3773 };
3774 
3775 class BasicStdLayoutCase4CS : public BasicStdLayoutBase2CS
3776 {
GetInput(std::vector<GLubyte> in_data[4])3777 	virtual const char* GetInput(std::vector<GLubyte> in_data[4])
3778 	{
3779 		return GetInputC4(in_data);
3780 	}
3781 };
3782 //-----------------------------------------------------------------------------
3783 // 1.10.x BasicOperationsBase
3784 //-----------------------------------------------------------------------------
3785 
3786 class BasicOperationsBaseVS : public ShaderStorageBufferObjectBase
3787 {
3788 	GLuint m_program;
3789 	GLuint m_buffer[2];
3790 	GLuint m_vertex_array;
3791 
3792 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3793 
Setup()3794 	virtual long Setup()
3795 	{
3796 		m_program = 0;
3797 		memset(m_buffer, 0, sizeof(m_buffer));
3798 		m_vertex_array = 0;
3799 		return NO_ERROR;
3800 	}
3801 
Run()3802 	virtual long Run()
3803 	{
3804 		if (!SupportedInVS(2))
3805 			return NOT_SUPPORTED;
3806 		std::vector<GLubyte> in_data;
3807 		std::vector<GLubyte> expected_data;
3808 		const char*			 glsl_vs = GetInput(in_data, expected_data);
3809 
3810 		m_program = CreateProgram(glsl_vs, "");
3811 		glLinkProgram(m_program);
3812 		if (!CheckProgram(m_program))
3813 			return ERROR;
3814 
3815 		glGenBuffers(2, m_buffer);
3816 
3817 		/* output buffer */
3818 		{
3819 			std::vector<GLubyte> zero(expected_data.size());
3820 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3821 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3822 		}
3823 		// input buffer
3824 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3825 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3826 
3827 		glGenVertexArrays(1, &m_vertex_array);
3828 		glEnable(GL_RASTERIZER_DISCARD);
3829 
3830 		glUseProgram(m_program);
3831 		glBindVertexArray(m_vertex_array);
3832 		glDrawArrays(GL_POINTS, 0, 1);
3833 
3834 		std::vector<GLubyte> out_data(expected_data.size());
3835 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3836 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3837 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)out_data.size(), &out_data[0]);
3838 
3839 		bool status = true;
3840 		for (size_t i = 0; i < out_data.size(); ++i)
3841 		{
3842 			if (expected_data[i] != out_data[i])
3843 			{
3844 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3845 													<< " is " << tcu::toHex(out_data[i]) << " should be "
3846 													<< tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3847 				status = false;
3848 			}
3849 		}
3850 		if (!status)
3851 			return ERROR;
3852 		return NO_ERROR;
3853 	}
3854 
Cleanup()3855 	virtual long Cleanup()
3856 	{
3857 		glDisable(GL_RASTERIZER_DISCARD);
3858 		glUseProgram(0);
3859 		glDeleteProgram(m_program);
3860 		glDeleteBuffers(2, m_buffer);
3861 		glDeleteVertexArrays(1, &m_vertex_array);
3862 		return NO_ERROR;
3863 	}
3864 };
3865 
3866 class BasicOperationsBaseCS : public ShaderStorageBufferObjectBase
3867 {
3868 	GLuint m_program;
3869 	GLuint m_buffer[2];
3870 
3871 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data) = 0;
3872 
Setup()3873 	virtual long Setup()
3874 	{
3875 		m_program = 0;
3876 		memset(m_buffer, 0, sizeof(m_buffer));
3877 		return NO_ERROR;
3878 	}
3879 
Run()3880 	virtual long Run()
3881 	{
3882 		std::vector<GLubyte> in_data;
3883 		std::vector<GLubyte> expected_data;
3884 
3885 		std::stringstream ss;
3886 		ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data, expected_data);
3887 		m_program = CreateProgramCS(ss.str());
3888 		glLinkProgram(m_program);
3889 		if (!CheckProgram(m_program))
3890 			return ERROR;
3891 
3892 		glGenBuffers(2, m_buffer);
3893 
3894 		/* output buffer */
3895 		{
3896 			std::vector<GLubyte> zero(expected_data.size());
3897 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
3898 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)expected_data.size(), &zero[0], GL_STATIC_DRAW);
3899 		}
3900 		// input buffer
3901 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
3902 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data.size(), &in_data[0], GL_STATIC_DRAW);
3903 
3904 		glUseProgram(m_program);
3905 		glUniform3f(glGetUniformLocation(m_program, "g_value0"), 10.0, 20.0, 30.0);
3906 		glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
3907 		glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
3908 		glDispatchCompute(1, 1, 1);
3909 
3910 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
3911 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3912 		GLubyte* out_data =
3913 			(GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)expected_data.size(), GL_MAP_READ_BIT);
3914 		if (!out_data)
3915 			return ERROR;
3916 
3917 		bool status = true;
3918 		for (size_t i = 0; i < expected_data.size(); ++i)
3919 		{
3920 			if (expected_data[i] != out_data[i])
3921 			{
3922 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Byte at index " << static_cast<int>(i)
3923 													<< " is " << tcu::toHex(out_data[i]) << " should be "
3924 													<< tcu::toHex(expected_data[i]) << tcu::TestLog::EndMessage;
3925 				status = false;
3926 			}
3927 		}
3928 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3929 		if (!status)
3930 			return ERROR;
3931 		return NO_ERROR;
3932 	}
3933 
Cleanup()3934 	virtual long Cleanup()
3935 	{
3936 		glUseProgram(0);
3937 		glDeleteProgram(m_program);
3938 		glDeleteBuffers(2, m_buffer);
3939 		return NO_ERROR;
3940 	}
3941 };
3942 
3943 //-----------------------------------------------------------------------------
3944 // 1.10.1 BasicOperationsCase1
3945 //-----------------------------------------------------------------------------
GetInputOp1(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)3946 const char* GetInputOp1(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
3947 {
3948 	/* input */
3949 	{
3950 		in_data.resize(16 * 9);
3951 		int*   ip = reinterpret_cast<int*>(&in_data[0]);
3952 		float* fp = reinterpret_cast<float*>(&in_data[0]);
3953 		ip[0]	 = 1;
3954 		ip[1]	 = 2;
3955 		ip[2]	 = 3;
3956 		ip[3]	 = 4;
3957 		fp[4]	 = 1.0f;
3958 		fp[5]	 = 2.0f;
3959 		fp[6]	 = 3.0f;
3960 		fp[7]	 = 0.0f;
3961 		ip[8]	 = 1;
3962 		ip[9]	 = 2;
3963 		ip[10]	= 3;
3964 		ip[11]	= 4;
3965 		ip[12]	= 1;
3966 		ip[13]	= -2;
3967 		ip[14]	= 3;
3968 		ip[15]	= 4;
3969 		fp[16]	= 1.0f;
3970 		fp[17]	= 2.0f;
3971 		fp[18]	= 3.0f;
3972 		fp[19]	= 4.0f;
3973 		fp[20]	= 1.0f;
3974 		fp[21]	= 2.0f;
3975 		fp[22]	= 3.0f;
3976 		fp[23]	= 4.0f;
3977 		fp[24]	= 1.0f;
3978 		fp[25]	= 2.0f;
3979 		fp[26]	= 3.0f;
3980 		fp[27]	= 4.0f;
3981 		fp[28]	= 1.0f;
3982 		fp[29]	= 2.0f;
3983 		fp[30]	= 3.0f;
3984 		fp[31]	= 4.0f;
3985 		fp[32]	= 1.0f;
3986 		fp[33]	= 0.0f;
3987 		fp[34]	= 0.0f;
3988 		fp[35]	= 4.0f;
3989 	}
3990 	/* expected output */
3991 	{
3992 		out_data.resize(16 * 9);
3993 		int*   ip = reinterpret_cast<int*>(&out_data[0]);
3994 		float* fp = reinterpret_cast<float*>(&out_data[0]);
3995 		ip[0]	 = 4;
3996 		ip[1]	 = 3;
3997 		ip[2]	 = 2;
3998 		ip[3]	 = 1;
3999 		fp[4]	 = 3.0f;
4000 		fp[5]	 = 2.0f;
4001 		fp[6]	 = 1.0f;
4002 		fp[7]	 = 0.0f;
4003 		ip[8]	 = 4;
4004 		ip[9]	 = 1;
4005 		ip[10]	= 0;
4006 		ip[11]	= 3;
4007 		ip[12]	= 10;
4008 		ip[13]	= 4;
4009 		ip[14]	= -2;
4010 		ip[15]	= 20;
4011 		fp[16]	= 50.0f;
4012 		fp[17]	= 5.0f;
4013 		fp[18]	= 2.0f;
4014 		fp[19]	= 30.0f;
4015 		fp[20]	= 4.0f;
4016 		fp[21]	= 2.0f;
4017 		fp[22]	= 3.0f;
4018 		fp[23]	= 1.0f;
4019 		fp[24]	= 4.0f;
4020 		fp[25]	= 3.0f;
4021 		fp[26]	= 2.0f;
4022 		fp[27]	= 1.0f;
4023 		fp[28]	= 2.0f;
4024 		fp[29]	= 2.0f;
4025 		fp[30]	= 2.0f;
4026 		fp[31]	= 2.0f;
4027 		fp[32]	= 4.0f;
4028 		fp[33]	= 0.0f;
4029 		fp[34]	= 0.0f;
4030 		fp[35]	= 1.0f;
4031 	}
4032 	return NL "layout(std430, binding = 0) buffer Input {" NL "  ivec4 data0;" NL "  vec3 data1;" NL "  uvec4 data2;" NL
4033 			  "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_input;" NL
4034 			  "layout(std430, binding = 1) buffer Output {" NL "  ivec4 data0;" NL "  vec3 data1;" NL
4035 			  "  uvec4 data2;" NL "  ivec4 data3;" NL "  vec4 data4;" NL "  mat4 data5;" NL "} g_output;" NL
4036 			  "uniform vec3 g_value0 = vec3(10, 20, 30);" NL "uniform int g_index1 = 1;" NL "void main() {" NL
4037 			  "  int index0 = 0;" NL "  g_output.data0.wzyx = g_input.data0;" NL
4038 			  "  g_output.data1 = g_input.data1.zyx;" NL "  g_output.data2.xwy = g_input.data2.wzx;" NL
4039 			  "  g_output.data3.xw = ivec2(10, 20);" NL "  g_output.data3.zy = g_input.data3.yw;" NL
4040 			  "  g_output.data4.wx = g_value0.xz;" NL "  g_output.data4.wx += g_value0.yy;" NL
4041 			  "  g_output.data4.yz = g_input.data4.xx + g_input.data4.wx;" NL
4042 			  "  g_output.data5[g_index1 - 1].wyzx = vec4(1, 2, 3, 4);" NL
4043 			  "  g_output.data5[g_index1 + index0] = g_input.data5[g_index1].wzyx;" NL
4044 			  "  g_output.data5[1 + g_index1] = g_input.data5[g_index1 + 1].yyyy;" NL
4045 			  "  g_output.data5[5 - g_index1 - 1].wx = g_input.data5[4 - g_index1].xw;" NL "}";
4046 }
4047 
4048 class BasicOperationsCase1VS : public BasicOperationsBaseVS
4049 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4050 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
4051 	{
4052 		return GetInputOp1(in_data, out_data);
4053 	}
4054 };
4055 
4056 class BasicOperationsCase1CS : public BasicOperationsBaseCS
4057 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4058 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
4059 	{
4060 		return GetInputOp1(in_data, out_data);
4061 	}
4062 };
4063 //-----------------------------------------------------------------------------
4064 // 1.10.2 BasicOperationsCase2
4065 //-----------------------------------------------------------------------------
GetInputOp2(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4066 const char* GetInputOp2(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
4067 {
4068 	/* input */
4069 	{
4070 		in_data.resize(16 * 8);
4071 		float* fp = reinterpret_cast<float*>(&in_data[0]);
4072 		fp[0]	 = 1.0f;
4073 		fp[1]	 = 0.0f;
4074 		fp[2]	 = 0.0f;
4075 		fp[3]	 = 0.0f;
4076 		fp[4]	 = 0.0f;
4077 		fp[5]	 = 1.0f;
4078 		fp[6]	 = 0.0f;
4079 		fp[7]	 = 0.0f;
4080 		fp[8]	 = 0.0f;
4081 		fp[9]	 = 0.0f;
4082 		fp[10]	= 1.0f;
4083 		fp[11]	= 0.0f;
4084 		fp[12]	= 0.0f;
4085 		fp[13]	= 0.0f;
4086 		fp[14]	= 0.0f;
4087 		fp[15]	= 1.0f;
4088 
4089 		fp[16] = 2.0f;
4090 		fp[17] = 0.0f;
4091 		fp[18] = 0.0f;
4092 		fp[19] = 0.0f;
4093 		fp[20] = 0.0f;
4094 		fp[21] = 3.0f;
4095 		fp[22] = 0.0f;
4096 		fp[23] = 0.0f;
4097 		fp[24] = 0.0f;
4098 		fp[25] = 0.0f;
4099 		fp[26] = 4.0f;
4100 		fp[27] = 0.0f;
4101 		fp[28] = 0.0f;
4102 		fp[29] = 0.0f;
4103 		fp[30] = 0.0f;
4104 		fp[31] = 5.0f;
4105 	}
4106 	/* expected output */
4107 	{
4108 		out_data.resize(16 * 5);
4109 		float* fp = reinterpret_cast<float*>(&out_data[0]);
4110 		fp[0]	 = 2.0f;
4111 		fp[1]	 = 0.0f;
4112 		fp[2]	 = 0.0f;
4113 		fp[3]	 = 0.0f;
4114 		fp[4]	 = 0.0f;
4115 		fp[5]	 = 3.0f;
4116 		fp[6]	 = 0.0f;
4117 		fp[7]	 = 0.0f;
4118 		fp[8]	 = 0.0f;
4119 		fp[9]	 = 0.0f;
4120 		fp[10]	= 4.0f;
4121 		fp[11]	= 0.0f;
4122 		fp[12]	= 0.0f;
4123 		fp[13]	= 0.0f;
4124 		fp[14]	= 0.0f;
4125 		fp[15]	= 5.0f;
4126 
4127 		fp[16] = 0.0f;
4128 		fp[17] = 1.0f;
4129 		fp[18] = 4.0f;
4130 		fp[19] = 0.0f;
4131 	}
4132 	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat4 data0;" NL "  mat4 data1;" NL "} g_input;" NL
4133 			  "layout(std430, binding = 1) buffer Output {" NL "  mat4 data0;" NL "  vec4 data1;" NL "} g_output;" NL
4134 			  "uniform int g_index2 = 2;" NL "void main() {" NL
4135 			  "  g_output.data0 = matrixCompMult(g_input.data0, g_input.data1);" NL
4136 			  "  g_output.data1 = g_input.data0[1] + g_input.data1[g_index2];" NL "}";
4137 }
4138 
4139 class BasicOperationsCase2VS : public BasicOperationsBaseVS
4140 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4141 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
4142 	{
4143 		return GetInputOp2(in_data, out_data);
4144 	}
4145 };
4146 
4147 class BasicOperationsCase2CS : public BasicOperationsBaseCS
4148 {
GetInput(std::vector<GLubyte> & in_data,std::vector<GLubyte> & out_data)4149 	virtual const char* GetInput(std::vector<GLubyte>& in_data, std::vector<GLubyte>& out_data)
4150 	{
4151 		return GetInputOp2(in_data, out_data);
4152 	}
4153 };
4154 
4155 //-----------------------------------------------------------------------------
4156 // 1.11.x BasicStdLayoutBase3
4157 //-----------------------------------------------------------------------------
4158 class BasicStdLayoutBase3VS : public ShaderStorageBufferObjectBase
4159 {
4160 	GLuint m_program;
4161 	GLuint m_buffer[4];
4162 	GLuint m_vertex_array;
4163 
4164 	virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
4165 
Setup()4166 	virtual long Setup()
4167 	{
4168 		m_program = 0;
4169 		memset(m_buffer, 0, sizeof(m_buffer));
4170 		m_vertex_array = 0;
4171 		return NO_ERROR;
4172 	}
4173 
Run()4174 	virtual long Run()
4175 	{
4176 		if (!SupportedInVS(2))
4177 			return NOT_SUPPORTED;
4178 		std::vector<GLubyte> in_data[2];
4179 		const char*			 glsl_vs = GetInput(in_data);
4180 
4181 		m_program = CreateProgram(glsl_vs, "");
4182 		glLinkProgram(m_program);
4183 		if (!CheckProgram(m_program))
4184 			return ERROR;
4185 
4186 		glGenBuffers(4, m_buffer);
4187 
4188 		// input buffers
4189 		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4190 		glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4191 
4192 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4193 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4194 
4195 		/* output buffer 0 */
4196 		{
4197 			std::vector<GLubyte> out_data(in_data[0].size());
4198 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4199 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4200 		}
4201 		/* output buffer 1 */
4202 		{
4203 			std::vector<GLubyte> out_data(in_data[1].size());
4204 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4205 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4206 		}
4207 
4208 		glGenVertexArrays(1, &m_vertex_array);
4209 		glEnable(GL_RASTERIZER_DISCARD);
4210 
4211 		glUseProgram(m_program);
4212 		glBindVertexArray(m_vertex_array);
4213 		glDrawArrays(GL_POINTS, 0, 1);
4214 
4215 		bool status = true;
4216 		for (int j = 0; j < 2; ++j)
4217 		{
4218 			std::vector<GLubyte> out_data(in_data[j].size());
4219 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4220 			glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4221 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), &out_data[0]);
4222 
4223 			for (size_t i = 0; i < in_data[j].size(); ++i)
4224 			{
4225 				if (in_data[j][i] != out_data[i])
4226 				{
4227 					m_context.getTestContext().getLog()
4228 						<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4229 						<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4230 						<< tcu::TestLog::EndMessage;
4231 					status = false;
4232 				}
4233 			}
4234 		}
4235 		if (!status)
4236 			return ERROR;
4237 		return NO_ERROR;
4238 	}
4239 
Cleanup()4240 	virtual long Cleanup()
4241 	{
4242 		glDisable(GL_RASTERIZER_DISCARD);
4243 		glUseProgram(0);
4244 		glDeleteProgram(m_program);
4245 		glDeleteBuffers(4, m_buffer);
4246 		glDeleteVertexArrays(1, &m_vertex_array);
4247 		return NO_ERROR;
4248 	}
4249 };
4250 
4251 class BasicStdLayoutBase3CS : public ShaderStorageBufferObjectBase
4252 {
4253 	GLuint m_program;
4254 	GLuint m_buffer[4];
4255 
4256 	virtual const char* GetInput(std::vector<GLubyte> in_data[2]) = 0;
4257 
Setup()4258 	virtual long Setup()
4259 	{
4260 		m_program = 0;
4261 		memset(m_buffer, 0, sizeof(m_buffer));
4262 		return NO_ERROR;
4263 	}
4264 
Run()4265 	virtual long Run()
4266 	{
4267 		std::vector<GLubyte> in_data[2];
4268 
4269 		std::stringstream ss;
4270 		ss << "layout(local_size_x = 1) in;\n" << GetInput(in_data);
4271 		m_program = CreateProgramCS(ss.str());
4272 		glLinkProgram(m_program);
4273 		if (!CheckProgram(m_program))
4274 			return ERROR;
4275 
4276 		glGenBuffers(4, m_buffer);
4277 
4278 		// input buffers
4279 		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer[0]);
4280 		glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)in_data[0].size(), &in_data[0][0], GL_STATIC_DRAW);
4281 
4282 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
4283 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &in_data[1][0], GL_STATIC_DRAW);
4284 
4285 		/* output buffer 0 */
4286 		{
4287 			std::vector<GLubyte> out_data(in_data[0].size());
4288 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[2]);
4289 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[0].size(), &out_data[0], GL_STATIC_DRAW);
4290 		}
4291 		/* output buffer 1 */
4292 		{
4293 			std::vector<GLubyte> out_data(in_data[1].size());
4294 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
4295 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)in_data[1].size(), &out_data[0], GL_STATIC_DRAW);
4296 		}
4297 
4298 		glUseProgram(m_program);
4299 		glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
4300 		glDispatchCompute(1, 1, 1);
4301 
4302 		bool status = true;
4303 		for (int j = 0; j < 2; ++j)
4304 		{
4305 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[j + 2]);
4306 			glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4307 			GLubyte* out_data =
4308 				(GLubyte*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)in_data[j].size(), GL_MAP_READ_BIT);
4309 			if (!out_data)
4310 				return ERROR;
4311 
4312 			for (size_t i = 0; i < in_data[j].size(); ++i)
4313 			{
4314 				if (in_data[j][i] != out_data[i])
4315 				{
4316 					m_context.getTestContext().getLog()
4317 						<< tcu::TestLog::Message << "Byte at index " << static_cast<int>(i) << " is "
4318 						<< tcu::toHex(out_data[i]) << " should be " << tcu::toHex(in_data[j][i])
4319 						<< tcu::TestLog::EndMessage;
4320 					status = false;
4321 				}
4322 			}
4323 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4324 		}
4325 		if (!status)
4326 			return ERROR;
4327 		return NO_ERROR;
4328 	}
4329 
Cleanup()4330 	virtual long Cleanup()
4331 	{
4332 		glUseProgram(0);
4333 		glDeleteProgram(m_program);
4334 		glDeleteBuffers(4, m_buffer);
4335 		return NO_ERROR;
4336 	}
4337 };
4338 //-----------------------------------------------------------------------------
4339 // 1.11.1 Basic_UBO_SSBO_LayoutCase1
4340 //-----------------------------------------------------------------------------
GetInputUBO1(std::vector<GLubyte> in_data[2])4341 const char* GetInputUBO1(std::vector<GLubyte> in_data[2])
4342 {
4343 	/* UBO */
4344 	{
4345 		in_data[0].resize(12 * 4);
4346 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4347 		fp[0]	 = 1.0f;
4348 		fp[1]	 = 0.0f;
4349 		fp[2]	 = 0.0f;
4350 		fp[3]	 = 0.0f;
4351 		fp[4]	 = 2.0f;
4352 		fp[5]	 = 0.0f;
4353 		fp[6]	 = 0.0f;
4354 		fp[7]	 = 0.0f;
4355 		fp[8]	 = 3.0f;
4356 		fp[9]	 = 0.0f;
4357 		fp[10]	= 0.0f;
4358 		fp[11]	= 0.0f;
4359 	}
4360 	/* SSBO */
4361 	{
4362 		in_data[1].resize(3 * 4);
4363 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4364 		fp[0]	 = 1.0f;
4365 		fp[1]	 = 2.0f;
4366 		fp[2]	 = 3.0f;
4367 	}
4368 	return NL
4369 		"layout(std140, binding = 0) uniform InputUBO {" NL "  float data0;" NL "  float data1[2];" NL
4370 		"} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL "  float data0;" NL
4371 		"  float data1[2];" NL "} g_input_ssbo;" NL "layout(std140, binding = 1) buffer OutputUBO {" NL
4372 		"  float data0;" NL "  float data1[2];" NL "} g_output_ubo;" NL
4373 		"layout(std430, binding = 2) buffer OutputSSBO {" NL "  float data0;" NL "  float data1[2];" NL
4374 		"} g_output_ssbo;" NL "void main() {" NL "  g_output_ubo.data0 = g_input_ubo.data0;" NL
4375 		"  for (int i = 0; i < g_input_ubo.data1.length(); ++i) g_output_ubo.data1[i] = g_input_ubo.data1[i];" NL
4376 		"  g_output_ssbo.data0 = g_input_ssbo.data0;" NL
4377 		"  for (int i = 0; i < g_input_ssbo.data1.length(); ++i) g_output_ssbo.data1[i] = g_input_ssbo.data1[i];" NL
4378 		"}";
4379 }
4380 
4381 class Basic_UBO_SSBO_LayoutCase1VS : public BasicStdLayoutBase3VS
4382 {
GetInput(std::vector<GLubyte> in_data[2])4383 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4384 	{
4385 		return GetInputUBO1(in_data);
4386 	}
4387 };
4388 
4389 class Basic_UBO_SSBO_LayoutCase1CS : public BasicStdLayoutBase3CS
4390 {
GetInput(std::vector<GLubyte> in_data[2])4391 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4392 	{
4393 		return GetInputUBO1(in_data);
4394 	}
4395 };
4396 
4397 //-----------------------------------------------------------------------------
4398 // 1.11.2 Basic_UBO_SSBO_LayoutCase2
4399 //-----------------------------------------------------------------------------
GetInputUBO2(std::vector<GLubyte> in_data[2])4400 const char* GetInputUBO2(std::vector<GLubyte> in_data[2])
4401 {
4402 	/* UBO */
4403 	{
4404 		in_data[0].resize(280 * 4);
4405 		float* fp = reinterpret_cast<float*>(&in_data[0][0]);
4406 		int*   ip = reinterpret_cast<int*>(&in_data[0][0]);
4407 		fp[0]	 = 1.0f;
4408 		fp[1]	 = 2.0f;
4409 		fp[2]	 = 3.0f;
4410 		fp[3]	 = 4.0f;
4411 		fp[4]	 = 5.0f;
4412 		fp[5]	 = 6.0f;
4413 		fp[6]	 = 7.0f;
4414 		fp[8]	 = 9.0f;
4415 		fp[12]	= 10.0f;
4416 		fp[16]	= 11.0f;
4417 		fp[20]	= 12.0f;
4418 		fp[24]	= 13.0f;
4419 
4420 		ip[28] = 14;
4421 		for (int i = 0; i < 20; ++i)
4422 		{
4423 			fp[32 + i * 4] = static_cast<float>(15 + i);
4424 		}
4425 		ip[112] = 140;
4426 		for (int i = 0; i < 20; ++i)
4427 		{
4428 			fp[116 + i * 4] = static_cast<float>(150 + i);
4429 		}
4430 		ip[196] = 1400;
4431 		for (int i = 0; i < 20; ++i)
4432 		{
4433 			fp[200 + i * 4] = static_cast<float>(1500 + i);
4434 		}
4435 	}
4436 	/* SSBO */
4437 	{
4438 		in_data[1].resize(76 * 4);
4439 		float* fp = reinterpret_cast<float*>(&in_data[1][0]);
4440 		int*   ip = reinterpret_cast<int*>(&in_data[1][0]);
4441 		fp[0]	 = 1.0f;
4442 		fp[1]	 = 2.0f;
4443 		fp[2]	 = 3.0f;
4444 		fp[3]	 = 4.0f;
4445 		fp[4]	 = 5.0f;
4446 		fp[5]	 = 6.0f;
4447 		fp[6]	 = 7.0f;
4448 		fp[7]	 = 8.0f;
4449 		fp[8]	 = 9.0f;
4450 		fp[9]	 = 10.0f;
4451 		fp[10]	= 11.0f;
4452 		fp[11]	= 12.0f;
4453 		fp[12]	= 13.0f;
4454 		ip[13]	= 14;
4455 		fp[14]	= 15.0f;
4456 		fp[15]	= 16.0f;
4457 		fp[16]	= 17.0f;
4458 		fp[17]	= 18.0f;
4459 		fp[18]	= 19.0f;
4460 		fp[19]	= 20.0f;
4461 		fp[20]	= 21.0f;
4462 		fp[21]	= 22.0f;
4463 		fp[22]	= 23.0f;
4464 		fp[23]	= 24.0f;
4465 		fp[24]	= 25.0f;
4466 		fp[25]	= 26.0f;
4467 		fp[26]	= 27.0f;
4468 		fp[27]	= 28.0f;
4469 		fp[28]	= 29.0f;
4470 		fp[29]	= 30.0f;
4471 		fp[30]	= 31.0f;
4472 		fp[31]	= 32.0f;
4473 		fp[32]	= 33.0f;
4474 		fp[33]	= 34.0f;
4475 		ip[34]	= 35;
4476 		fp[35]	= 36.0f;
4477 		fp[36]	= 37.0f;
4478 		fp[37]	= 38.0f;
4479 		fp[38]	= 39.0f;
4480 		fp[39]	= 40.0f;
4481 		fp[40]	= 41.0f;
4482 		fp[41]	= 42.0f;
4483 		fp[42]	= 43.0f;
4484 		fp[43]	= 44.0f;
4485 		fp[44]	= 45.0f;
4486 		fp[45]	= 46.0f;
4487 		fp[46]	= 47.0f;
4488 		fp[47]	= 48.0f;
4489 		fp[48]	= 49.0f;
4490 		fp[49]	= 50.0f;
4491 		fp[50]	= 51.0f;
4492 		fp[51]	= 52.0f;
4493 		fp[52]	= 53.0f;
4494 		fp[53]	= 54.0f;
4495 		fp[54]	= 55.0f;
4496 		ip[55]	= 56;
4497 		fp[56]	= 57.0f;
4498 		fp[57]	= 58.0f;
4499 		fp[58]	= 59.0f;
4500 		fp[59]	= 60.0f;
4501 		fp[60]	= 61.0f;
4502 		fp[61]	= 62.0f;
4503 		fp[62]	= 63.0f;
4504 		fp[63]	= 64.0f;
4505 		fp[64]	= 65.0f;
4506 		fp[65]	= 66.0f;
4507 		fp[66]	= 67.0f;
4508 		fp[67]	= 68.0f;
4509 		fp[68]	= 69.0f;
4510 		fp[69]	= 70.0f;
4511 		fp[70]	= 71.0f;
4512 		fp[71]	= 72.0f;
4513 		fp[72]	= 73.0f;
4514 		fp[73]	= 74.0f;
4515 		fp[74]	= 75.0f;
4516 		fp[75]	= 76.0f;
4517 	}
4518 	return NL
4519 		"struct MM {" NL "  float mm_a[5];" NL "};" NL "struct TT {" NL "  int tt_a;" NL "  MM  tt_b[4];" NL "};" NL
4520 		"layout(std140, binding = 0) uniform InputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4521 		"  float d[4];" NL "  TT    e[3];" NL "} g_input_ubo;" NL "layout(std430, binding = 0) buffer InputSSBO {" NL
4522 		"  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_input_ssbo;" NL
4523 		"layout(std140, binding = 1) buffer OutputUBO {" NL "  vec4  a;" NL "  vec4  b;" NL "  float c;" NL
4524 		"  float d[4];" NL "  TT    e[3];" NL "} g_output_ubo;" NL "layout(std430, binding = 2) buffer OutputSSBO {" NL
4525 		"  vec4  a;" NL "  vec4  b;" NL "  float c;" NL "  float d[4];" NL "  TT    e[3];" NL "} g_output_ssbo;" NL
4526 		"uniform int g_index1 = 1;" NL "void main() {" NL "  int index0 = 0;" NL NL
4527 		"  g_output_ubo.a = g_input_ubo.a;" NL "  g_output_ubo.b = g_input_ubo.b;" NL
4528 		"  g_output_ubo.c = g_input_ubo.c;" NL
4529 		"  for (int i = 0; i < g_input_ubo.d.length(); ++i) g_output_ubo.d[i] = g_input_ubo.d[i];" NL
4530 		"    for (int j = 0; j < g_input_ubo.e.length(); ++j) {" NL
4531 		"    g_output_ubo.e[j].tt_a = g_input_ubo.e[j].tt_a;" NL
4532 		"    for (int i = 0; i < g_input_ubo.e[j].tt_b.length(); ++i) {" NL
4533 		"      g_output_ubo.e[j].tt_b[i].mm_a[0] = g_input_ubo.e[j].tt_b[i].mm_a[0];" NL
4534 		"      g_output_ubo.e[j].tt_b[index0 + i].mm_a[1] = g_input_ubo.e[j].tt_b[i].mm_a[1];" NL
4535 		"      g_output_ubo.e[j].tt_b[i].mm_a[2] = g_input_ubo.e[j].tt_b[i].mm_a[2 + index0];" NL
4536 		"      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 + "
4537 		"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
4538 		"    }" NL "  }" NL NL "  g_output_ssbo.a = g_input_ssbo.a;" NL "  g_output_ssbo.b = g_input_ssbo.b;" NL
4539 		"  g_output_ssbo.c = g_input_ssbo.c;" NL
4540 		"  for (int i = 0; i < g_input_ssbo.d.length(); ++i) g_output_ssbo.d[i] = g_input_ssbo.d[i];" NL
4541 		"  for (int j = 0; j < g_input_ssbo.e.length(); ++j) {" NL
4542 		"    g_output_ssbo.e[j].tt_a = g_input_ssbo.e[j].tt_a;" NL
4543 		"    for (int i = 0; i < g_input_ssbo.e[j].tt_b.length(); ++i) {" NL
4544 		"      g_output_ssbo.e[j + index0].tt_b[i].mm_a[0] = g_input_ssbo.e[j].tt_b[i].mm_a[index0];" NL
4545 		"      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
4546 		"      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
4547 		"      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 - "
4548 		"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
4549 		"  }" NL "}";
4550 }
4551 
4552 class Basic_UBO_SSBO_LayoutCase2VS : public BasicStdLayoutBase3VS
4553 {
GetInput(std::vector<GLubyte> in_data[2])4554 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4555 	{
4556 		return GetInputUBO2(in_data);
4557 	}
4558 };
4559 
4560 class Basic_UBO_SSBO_LayoutCase2CS : public BasicStdLayoutBase3CS
4561 {
GetInput(std::vector<GLubyte> in_data[2])4562 	virtual const char* GetInput(std::vector<GLubyte> in_data[2])
4563 	{
4564 		return GetInputUBO2(in_data);
4565 	}
4566 };
4567 
4568 //-----------------------------------------------------------------------------
4569 // 1.12.x BasicMatrixOperationsBase
4570 //-----------------------------------------------------------------------------
4571 
4572 class BasicMatrixOperationsBaseVS : public ShaderStorageBufferObjectBase
4573 {
4574 	GLuint m_program;
4575 	GLuint m_buffer[2];
4576 	GLuint m_vertex_array;
4577 
4578 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4579 
Equal(float a,float b)4580 	static bool Equal(float a, float b)
4581 	{
4582 		return fabsf(a - b) < 0.001f;
4583 	}
4584 
Setup()4585 	virtual long Setup()
4586 	{
4587 		m_program = 0;
4588 		memset(m_buffer, 0, sizeof(m_buffer));
4589 		m_vertex_array = 0;
4590 		return NO_ERROR;
4591 	}
4592 
Run()4593 	virtual long Run()
4594 	{
4595 		if (!SupportedInVS(2))
4596 			return NOT_SUPPORTED;
4597 		std::vector<float> in;
4598 		std::vector<float> expected;
4599 		const char*		   glsl_vs = GetInput(in, expected);
4600 
4601 		m_program = CreateProgram(glsl_vs, "");
4602 		glLinkProgram(m_program);
4603 		if (!CheckProgram(m_program))
4604 			return ERROR;
4605 
4606 		glGenBuffers(2, m_buffer);
4607 
4608 		/* output buffer */
4609 		{
4610 			std::vector<float> zero(expected.size());
4611 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4612 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4613 						 GL_STATIC_DRAW);
4614 		}
4615 		// input buffer
4616 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4617 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4618 
4619 		glGenVertexArrays(1, &m_vertex_array);
4620 		glEnable(GL_RASTERIZER_DISCARD);
4621 
4622 		glUseProgram(m_program);
4623 		glBindVertexArray(m_vertex_array);
4624 		glDrawArrays(GL_POINTS, 0, 1);
4625 
4626 		std::vector<float> out_data(expected.size());
4627 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4628 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4629 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, (GLsizeiptr)(out_data.size() * sizeof(float)), &out_data[0]);
4630 
4631 		bool status = true;
4632 		for (size_t i = 0; i < out_data.size(); ++i)
4633 		{
4634 			if (!Equal(expected[i], out_data[i]))
4635 			{
4636 				m_context.getTestContext().getLog()
4637 					<< tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4638 					<< " should be " << expected[i] << tcu::TestLog::EndMessage;
4639 				status = false;
4640 			}
4641 		}
4642 		if (!status)
4643 			return ERROR;
4644 		return NO_ERROR;
4645 	}
4646 
Cleanup()4647 	virtual long Cleanup()
4648 	{
4649 		glDisable(GL_RASTERIZER_DISCARD);
4650 		glUseProgram(0);
4651 		glDeleteProgram(m_program);
4652 		glDeleteBuffers(2, m_buffer);
4653 		glDeleteVertexArrays(1, &m_vertex_array);
4654 		return NO_ERROR;
4655 	}
4656 };
4657 
4658 class BasicMatrixOperationsBaseCS : public ShaderStorageBufferObjectBase
4659 {
4660 	GLuint m_program;
4661 	GLuint m_buffer[2];
4662 
4663 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected) = 0;
4664 
Equal(float a,float b)4665 	static bool Equal(float a, float b)
4666 	{
4667 		return fabsf(a - b) < 0.001f;
4668 	}
4669 
Setup()4670 	virtual long Setup()
4671 	{
4672 		m_program = 0;
4673 		memset(m_buffer, 0, sizeof(m_buffer));
4674 		return NO_ERROR;
4675 	}
4676 
Run()4677 	virtual long Run()
4678 	{
4679 		std::vector<float> in;
4680 		std::vector<float> expected;
4681 		std::stringstream  ss;
4682 		ss << "layout(local_size_x = 1) in;\n" << GetInput(in, expected);
4683 		m_program = CreateProgramCS(ss.str());
4684 		glLinkProgram(m_program);
4685 		if (!CheckProgram(m_program))
4686 			return ERROR;
4687 
4688 		glGenBuffers(2, m_buffer);
4689 
4690 		/* output buffer */
4691 		{
4692 			std::vector<float> zero(expected.size());
4693 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
4694 			glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(expected.size() * sizeof(float)), &zero[0],
4695 						 GL_STATIC_DRAW);
4696 		}
4697 		// input buffer
4698 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
4699 		glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(in.size() * sizeof(float)), &in[0], GL_STATIC_DRAW);
4700 
4701 		glUseProgram(m_program);
4702 		glDispatchCompute(1, 1, 1);
4703 
4704 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[1]);
4705 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4706 		float* out_data = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0,
4707 												   (GLsizeiptr)(expected.size() * sizeof(float)), GL_MAP_READ_BIT);
4708 		if (!out_data)
4709 			return ERROR;
4710 
4711 		bool status = true;
4712 		for (size_t i = 0; i < expected.size(); ++i)
4713 		{
4714 			if (!Equal(expected[i], out_data[i]))
4715 			{
4716 				m_context.getTestContext().getLog()
4717 					<< tcu::TestLog::Message << "Float at index " << static_cast<int>(i) << " is " << out_data[i]
4718 					<< " should be " << expected[i] << tcu::TestLog::EndMessage;
4719 				status = false;
4720 			}
4721 		}
4722 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
4723 		if (!status)
4724 			return ERROR;
4725 		return NO_ERROR;
4726 	}
4727 
Cleanup()4728 	virtual long Cleanup()
4729 	{
4730 		glUseProgram(0);
4731 		glDeleteProgram(m_program);
4732 		glDeleteBuffers(2, m_buffer);
4733 		return NO_ERROR;
4734 	}
4735 };
4736 //-----------------------------------------------------------------------------
4737 // 1.12.1 BasicMatrixOperationsCase1
4738 //-----------------------------------------------------------------------------
GetInputM1(std::vector<float> & in,std::vector<float> & expected)4739 const char* GetInputM1(std::vector<float>& in, std::vector<float>& expected)
4740 {
4741 	in.resize(8);
4742 	in[0] = 1.0f;
4743 	in[2] = 3.0f;
4744 	in[1] = 2.0f;
4745 	in[3] = 4.0f;
4746 	in[4] = 1.0f;
4747 	in[6] = 3.0f;
4748 	in[5] = 2.0f;
4749 	in[7] = 4.0f;
4750 	expected.resize(4);
4751 	expected[0] = 7.0f;
4752 	expected[2] = 15.0f;
4753 	expected[1] = 10.0f;
4754 	expected[3] = 22.0f;
4755 
4756 	return NL "layout(std430, binding = 0) buffer Input {" NL "  mat2 m0;" NL "  mat2 m1;" NL "} g_input;" NL
4757 			  "layout(std430, binding = 1) buffer Output {" NL "  mat2 m;" NL "} g_output;" NL
4758 			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4759 }
4760 
4761 class BasicMatrixOperationsCase1VS : public BasicMatrixOperationsBaseVS
4762 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4763 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4764 	{
4765 		return GetInputM1(in, expected);
4766 	}
4767 };
4768 
4769 class BasicMatrixOperationsCase1CS : public BasicMatrixOperationsBaseCS
4770 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4771 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4772 	{
4773 		return GetInputM1(in, expected);
4774 	}
4775 };
4776 
4777 //-----------------------------------------------------------------------------
4778 // 1.12.2 BasicMatrixOperationsCase2
4779 //-----------------------------------------------------------------------------
GetInputM2(std::vector<float> & in,std::vector<float> & expected)4780 const char* GetInputM2(std::vector<float>& in, std::vector<float>& expected)
4781 {
4782 	in.resize(16);
4783 	expected.resize(4);
4784 	// mat3x2
4785 	in[0] = 1.0f;
4786 	in[2] = 3.0f;
4787 	in[4] = 5.0f;
4788 	in[1] = 2.0f;
4789 	in[3] = 4.0f;
4790 	in[5] = 6.0f;
4791 	// mat2x3
4792 	in[8]  = 1.0f;
4793 	in[12] = 4.0f;
4794 	in[9]  = 2.0f;
4795 	in[13] = 5.0f;
4796 	in[10] = 3.0f;
4797 	in[14] = 6.0f;
4798 	// mat2
4799 	expected[0] = 22.0f;
4800 	expected[2] = 49.0f;
4801 	expected[1] = 28.0f;
4802 	expected[3] = 64.0f;
4803 
4804 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4805 			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4806 			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
4807 			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4808 }
4809 
4810 class BasicMatrixOperationsCase2VS : public BasicMatrixOperationsBaseVS
4811 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4812 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4813 	{
4814 		return GetInputM2(in, expected);
4815 	}
4816 };
4817 
4818 class BasicMatrixOperationsCase2CS : public BasicMatrixOperationsBaseCS
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 GetInputM2(in, expected);
4823 	}
4824 };
4825 
4826 //-----------------------------------------------------------------------------
4827 // 1.12.3 BasicMatrixOperationsCase3
4828 //-----------------------------------------------------------------------------
GetInputM3(std::vector<float> & in,std::vector<float> & expected)4829 const char* GetInputM3(std::vector<float>& in, std::vector<float>& expected)
4830 {
4831 	in.resize(16);
4832 	expected.resize(4);
4833 	// row major mat3x2
4834 	in[0] = 1.0f;
4835 	in[1] = 3.0f;
4836 	in[2] = 5.0f;
4837 	in[4] = 2.0f;
4838 	in[5] = 4.0f;
4839 	in[6] = 6.0f;
4840 	// row major mat2x3
4841 	in[8]  = 1.0f;
4842 	in[9]  = 4.0f;
4843 	in[10] = 2.0f;
4844 	in[11] = 5.0f;
4845 	in[12] = 3.0f;
4846 	in[13] = 6.0f;
4847 	// row major mat2
4848 	expected[0] = 22.0f;
4849 	expected[1] = 49.0f;
4850 	expected[2] = 28.0f;
4851 	expected[3] = 64.0f;
4852 
4853 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4854 			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4855 			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4856 }
4857 
4858 class BasicMatrixOperationsCase3VS : public BasicMatrixOperationsBaseVS
4859 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4860 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4861 	{
4862 		return GetInputM3(in, expected);
4863 	}
4864 };
4865 
4866 class BasicMatrixOperationsCase3CS : public BasicMatrixOperationsBaseCS
4867 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4868 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4869 	{
4870 		return GetInputM3(in, expected);
4871 	}
4872 };
4873 
4874 //-----------------------------------------------------------------------------
4875 // 1.12.4 BasicMatrixOperationsCase4
4876 //-----------------------------------------------------------------------------
GetInputM4(std::vector<float> & in,std::vector<float> & expected)4877 const char* GetInputM4(std::vector<float>& in, std::vector<float>& expected)
4878 {
4879 	in.resize(16);
4880 	expected.resize(4);
4881 	// column major mat3x2
4882 	in[0] = 1.0f;
4883 	in[2] = 3.0f;
4884 	in[4] = 5.0f;
4885 	in[1] = 2.0f;
4886 	in[3] = 4.0f;
4887 	in[5] = 6.0f;
4888 	// row major mat2x3
4889 	in[8]  = 1.0f;
4890 	in[9]  = 4.0f;
4891 	in[10] = 2.0f;
4892 	in[11] = 5.0f;
4893 	in[12] = 3.0f;
4894 	in[13] = 6.0f;
4895 	// column major mat2
4896 	expected[0] = 13.0f;
4897 	expected[1] = 16.0f;
4898 	expected[2] = 37.0f;
4899 	expected[3] = 46.0f;
4900 
4901 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4902 			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4903 			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
4904 			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4905 }
4906 
4907 class BasicMatrixOperationsCase4VS : public BasicMatrixOperationsBaseVS
4908 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4909 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4910 	{
4911 		return GetInputM4(in, expected);
4912 	}
4913 };
4914 
4915 class BasicMatrixOperationsCase4CS : public BasicMatrixOperationsBaseCS
4916 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4917 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4918 	{
4919 		return GetInputM4(in, expected);
4920 	}
4921 };
4922 
4923 //-----------------------------------------------------------------------------
4924 // 1.12.5 BasicMatrixOperationsCase5
4925 //-----------------------------------------------------------------------------
GetInputM5(std::vector<float> & in,std::vector<float> & expected)4926 const char* GetInputM5(std::vector<float>& in, std::vector<float>& expected)
4927 {
4928 	in.resize(16);
4929 	expected.resize(4);
4930 	// column major mat3x2
4931 	in[0] = 1.0f;
4932 	in[2] = 3.0f;
4933 	in[4] = 5.0f;
4934 	in[1] = 2.0f;
4935 	in[3] = 4.0f;
4936 	in[5] = 6.0f;
4937 	// row major mat2x3
4938 	in[8]  = 1.0f;
4939 	in[9]  = 4.0f;
4940 	in[10] = 2.0f;
4941 	in[11] = 5.0f;
4942 	in[12] = 3.0f;
4943 	in[13] = 6.0f;
4944 	// row major mat2
4945 	expected[0] = 13.0f;
4946 	expected[1] = 37.0f;
4947 	expected[2] = 16.0f;
4948 	expected[3] = 46.0f;
4949 
4950 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(column_major) mat3x2 m0;" NL
4951 			  "  layout(row_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
4952 			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
4953 }
4954 
4955 class BasicMatrixOperationsCase5VS : public BasicMatrixOperationsBaseVS
4956 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4957 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4958 	{
4959 		return GetInputM5(in, expected);
4960 	}
4961 };
4962 
4963 class BasicMatrixOperationsCase5CS : public BasicMatrixOperationsBaseCS
4964 {
GetInput(std::vector<float> & in,std::vector<float> & expected)4965 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
4966 	{
4967 		return GetInputM5(in, expected);
4968 	}
4969 };
4970 
4971 //-----------------------------------------------------------------------------
4972 // 1.12.6 BasicMatrixOperationsCase6
4973 //-----------------------------------------------------------------------------
GetInputM6(std::vector<float> & in,std::vector<float> & expected)4974 const char* GetInputM6(std::vector<float>& in, std::vector<float>& expected)
4975 {
4976 	in.resize(20);
4977 	expected.resize(4);
4978 	// row major mat3x2
4979 	in[0] = 1.0f;
4980 	in[1] = 3.0f;
4981 	in[2] = 5.0f;
4982 	in[4] = 2.0f;
4983 	in[5] = 4.0f;
4984 	in[6] = 6.0f;
4985 	// column major mat2x3
4986 	in[8]  = 1.0f;
4987 	in[12] = 4.0f;
4988 	in[9]  = 2.0f;
4989 	in[13] = 5.0f;
4990 	in[10] = 3.0f;
4991 	in[14] = 6.0f;
4992 	// column major mat2
4993 	expected[0] = 22.0f;
4994 	expected[1] = 28.0f;
4995 	expected[2] = 49.0f;
4996 	expected[3] = 64.0f;
4997 
4998 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
4999 			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5000 			  "  layout(column_major) mat2 m;" NL "} g_output;" NL
5001 			  "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5002 }
5003 
5004 class BasicMatrixOperationsCase6VS : public BasicMatrixOperationsBaseVS
5005 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5006 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
5007 	{
5008 		return GetInputM6(in, expected);
5009 	}
5010 };
5011 
5012 class BasicMatrixOperationsCase6CS : public BasicMatrixOperationsBaseCS
5013 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5014 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
5015 	{
5016 		return GetInputM6(in, expected);
5017 	}
5018 };
5019 //-----------------------------------------------------------------------------
5020 // 1.12.7 BasicMatrixOperationsCase7
5021 //-----------------------------------------------------------------------------
GetInputM7(std::vector<float> & in,std::vector<float> & expected)5022 const char* GetInputM7(std::vector<float>& in, std::vector<float>& expected)
5023 {
5024 	in.resize(20);
5025 	expected.resize(4);
5026 	// row major mat3x2
5027 	in[0] = 1.0f;
5028 	in[1] = 3.0f;
5029 	in[2] = 5.0f;
5030 	in[4] = 2.0f;
5031 	in[5] = 4.0f;
5032 	in[6] = 6.0f;
5033 	// column major mat2x3
5034 	in[8]  = 1.0f;
5035 	in[12] = 4.0f;
5036 	in[9]  = 2.0f;
5037 	in[13] = 5.0f;
5038 	in[10] = 3.0f;
5039 	in[14] = 6.0f;
5040 	// row major mat2
5041 	expected[0] = 22.0f;
5042 	expected[1] = 49.0f;
5043 	expected[2] = 28.0f;
5044 	expected[3] = 64.0f;
5045 
5046 	return NL "layout(std430, binding = 0) buffer Input {" NL "  layout(row_major) mat3x2 m0;" NL
5047 			  "  layout(column_major) mat2x3 m1;" NL "} g_input;" NL "layout(std430, binding = 1) buffer Output {" NL
5048 			  "  layout(row_major) mat2 m;" NL "} g_output;" NL "void main() { g_output.m = g_input.m0 * g_input.m1; }";
5049 }
5050 
5051 class BasicMatrixOperationsCase7VS : public BasicMatrixOperationsBaseVS
5052 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5053 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
5054 	{
5055 		return GetInputM7(in, expected);
5056 	}
5057 };
5058 
5059 class BasicMatrixOperationsCase7CS : public BasicMatrixOperationsBaseCS
5060 {
GetInput(std::vector<float> & in,std::vector<float> & expected)5061 	virtual const char* GetInput(std::vector<float>& in, std::vector<float>& expected)
5062 	{
5063 		return GetInputM7(in, expected);
5064 	}
5065 };
5066 
5067 //-----------------------------------------------------------------------------
5068 // 1.13 BasicNoBindingLayout
5069 //-----------------------------------------------------------------------------
5070 class BasicNoBindingLayout : public ShaderStorageBufferObjectBase
5071 {
5072 	GLuint m_vsp, m_ppo, m_ssbo, m_vao;
5073 
Setup()5074 	virtual long Setup()
5075 	{
5076 		m_vsp = 0;
5077 		glGenProgramPipelines(1, &m_ppo);
5078 		glGenBuffers(1, &m_ssbo);
5079 		glGenVertexArrays(1, &m_vao);
5080 		return NO_ERROR;
5081 	}
5082 
Cleanup()5083 	virtual long Cleanup()
5084 	{
5085 		glDisable(GL_RASTERIZER_DISCARD);
5086 		glDeleteProgram(m_vsp);
5087 		glDeleteProgramPipelines(1, &m_ppo);
5088 		glDeleteBuffers(1, &m_ssbo);
5089 		glDeleteVertexArrays(1, &m_vao);
5090 		return NO_ERROR;
5091 	}
5092 
Run()5093 	virtual long Run()
5094 	{
5095 		if (!SupportedInVS(3))
5096 			return NOT_SUPPORTED;
5097 
5098 		const char* const glsl_vs = "#version 430 core" NL "layout(std430) buffer Output0 { int data; } g_output0;" NL
5099 									"layout(std430) buffer Output1 { int g_output1; };" NL
5100 									"layout(std430) buffer Output2 { int data; } g_output2;" NL "void main() {" NL
5101 									"  g_output0.data = 1;" NL "  g_output1 = 2;" NL "  g_output2.data = 3;" NL "}";
5102 		m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
5103 		if (!CheckProgram(m_vsp))
5104 			return ERROR;
5105 		glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
5106 
5107 		glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output0"), 1);
5108 		glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output1"), 5);
5109 		glShaderStorageBlockBinding(m_vsp, glGetProgramResourceIndex(m_vsp, GL_SHADER_STORAGE_BLOCK, "Output2"), 7);
5110 
5111 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5112 		glBufferData(GL_SHADER_STORAGE_BUFFER, 1024, NULL, GL_DYNAMIC_DRAW);
5113 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, m_ssbo, 0, 4);
5114 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 5, m_ssbo, 256, 4);
5115 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 7, m_ssbo, 512, 4);
5116 
5117 		glEnable(GL_RASTERIZER_DISCARD);
5118 		glBindProgramPipeline(m_ppo);
5119 		glBindVertexArray(m_vao);
5120 		glDrawArrays(GL_POINTS, 0, 1);
5121 
5122 		int data;
5123 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
5124 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5125 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, 4, &data);
5126 		if (data != 1)
5127 			return ERROR;
5128 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 256, 4, &data);
5129 		if (data != 2)
5130 			return ERROR;
5131 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 512, 4, &data);
5132 		if (data != 3)
5133 			return ERROR;
5134 
5135 		return NO_ERROR;
5136 	}
5137 };
5138 
5139 //----------------------------------------------------------------------------
5140 // 1.14 BasicReadonlyWriteonly
5141 //-----------------------------------------------------------------------------
5142 class BasicReadonlyWriteonly : public ShaderStorageBufferObjectBase
5143 {
5144 	GLuint m_program;
5145 	GLuint m_storage_buffer[2];
5146 
Setup()5147 	virtual long Setup()
5148 	{
5149 		m_program = 0;
5150 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5151 		return NO_ERROR;
5152 	}
5153 
Run()5154 	virtual long Run()
5155 	{
5156 		const char* const glsl_cs =
5157 			NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Input {" NL
5158 			   "  readonly writeonly int g_in[];" NL "};" NL "layout(std430, binding = 1) buffer Output {" NL
5159 			   "  int count;" NL "} g_output;" NL "void main() {" NL "  g_output.count = g_in.length();" NL "}";
5160 
5161 		m_program = CreateProgramCS(glsl_cs);
5162 		glLinkProgram(m_program);
5163 		if (!CheckProgram(m_program))
5164 			return ERROR;
5165 
5166 		glGenBuffers(2, m_storage_buffer);
5167 
5168 		/* Input */
5169 		int input_data[] = { 1, 2, 3 };
5170 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5171 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(input_data), input_data, GL_STATIC_DRAW);
5172 
5173 		/* Output */
5174 		int output_data[] = { 0 };
5175 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5176 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(output_data), output_data, GL_DYNAMIC_COPY);
5177 
5178 		glUseProgram(m_program);
5179 		glDispatchCompute(1, 1, 1);
5180 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5181 
5182 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5183 		int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
5184 		if (!data)
5185 			return ERROR;
5186 		if (*data != DE_LENGTH_OF_ARRAY(input_data))
5187 		{
5188 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer data is " << *data << " should be "
5189 												<< sizeof(input_data) << tcu::TestLog::EndMessage;
5190 			return ERROR;
5191 		}
5192 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5193 		return NO_ERROR;
5194 	}
5195 
Cleanup()5196 	virtual long Cleanup()
5197 	{
5198 		glUseProgram(0);
5199 		glDeleteProgram(m_program);
5200 		glDeleteBuffers(2, m_storage_buffer);
5201 		return NO_ERROR;
5202 	}
5203 };
5204 
5205 //----------------------------------------------------------------------------
5206 // 1.15 BasicNameMatch
5207 //-----------------------------------------------------------------------------
5208 class BasicNameMatch : public ShaderStorageBufferObjectBase
5209 {
Run()5210 	virtual long Run()
5211 	{
5212 		GLint blocksVS, blocksFS;
5213 		glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
5214 		glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
5215 		if ((blocksVS == 0) || (blocksFS == 0))
5216 			return NOT_SUPPORTED;
5217 
5218 		// check if link error is generated when one of matched blocks has instance name and other doesn't
5219 		std::string vs1("buffer Buf { float x; };\n"
5220 						"void main() {\n"
5221 						"  gl_Position = vec4(x);\n"
5222 						"}");
5223 		std::string fs1("buffer Buf { float x; } b;\n"
5224 						"out vec4 color;\n"
5225 						"void main() {\n"
5226 						"  color = vec4(b.x);\n"
5227 						"}");
5228 		if (Link(vs1, fs1))
5229 		{
5230 			m_context.getTestContext().getLog()
5231 				<< tcu::TestLog::Message << "Linking should fail." << tcu::TestLog::EndMessage;
5232 			return ERROR;
5233 		}
5234 
5235 		// check if linking succeeds when both matched blocks are lacking an instance name
5236 		std::string vs2("buffer Buf { float x; };\n"
5237 						"void main() {\n"
5238 						"  gl_Position = vec4(x);\n"
5239 						"}");
5240 		std::string fs2("buffer Buf { float x; };\n"
5241 						"out vec4 color;\n"
5242 						"void main() {\n"
5243 						"  color = vec4(x);\n"
5244 						"}");
5245 		if (!Link(vs2, fs2))
5246 		{
5247 			m_context.getTestContext().getLog()
5248 				<< tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5249 			return ERROR;
5250 		}
5251 
5252 		// check if linking succeeds when both matched blocks have different instance names
5253 		std::string vs3("buffer Buf { float x; } a;\n"
5254 						"void main() {\n"
5255 						"  gl_Position = vec4(a.x);\n"
5256 						"}");
5257 		std::string fs3("buffer Buf { float x; } b;\n"
5258 						"out vec4 color;\n"
5259 						"void main() {\n"
5260 						"  color = vec4(b.x);\n"
5261 						"}");
5262 		if (!Link(vs3, fs3))
5263 		{
5264 			m_context.getTestContext().getLog()
5265 				<< tcu::TestLog::Message << "Linking should succeed." << tcu::TestLog::EndMessage;
5266 			return ERROR;
5267 		}
5268 
5269 		return NO_ERROR;
5270 	}
5271 
Link(const std::string & vs,const std::string & fs)5272 	bool Link(const std::string& vs, const std::string& fs)
5273 	{
5274 		GLuint program = CreateProgram(vs, fs);
5275 		glLinkProgram(program);
5276 		GLint status;
5277 		glGetProgramiv(program, GL_LINK_STATUS, &status);
5278 		glDeleteProgram(program);
5279 		return (status == GL_TRUE);
5280 	}
5281 };
5282 
5283 //-----------------------------------------------------------------------------
5284 // 2.1 AdvancedSwitchBuffers
5285 //-----------------------------------------------------------------------------
5286 class AdvancedSwitchBuffers : public ShaderStorageBufferObjectBase
5287 {
5288 	GLuint m_program;
5289 	GLuint m_storage_buffer[5];
5290 	GLuint m_vertex_array;
5291 	GLuint m_fbo, m_rt;
5292 
Setup()5293 	virtual long Setup()
5294 	{
5295 		m_program = 0;
5296 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5297 		m_vertex_array = 0;
5298 		glGenFramebuffers(1, &m_fbo);
5299 		glGenTextures(1, &m_rt);
5300 		return NO_ERROR;
5301 	}
5302 
Run()5303 	virtual long Run()
5304 	{
5305 		if (!SupportedInVS(1))
5306 			return NOT_SUPPORTED;
5307 
5308 		const char* const glsl_vs =
5309 			NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL
5310 			   "layout(binding = 0, std430) buffer Input {" NL "  VertexData vertex[];" NL "} g_vs_in;" NL
5311 			   "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5312 			   "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5313 			   "  g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5314 
5315 		const char* const glsl_fs =
5316 			NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5317 			   "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5318 		m_program = CreateProgram(glsl_vs, glsl_fs);
5319 		glLinkProgram(m_program);
5320 		if (!CheckProgram(m_program))
5321 			return ERROR;
5322 
5323 		glGenBuffers(5, m_storage_buffer);
5324 
5325 		/* left, bottom, red quad */
5326 		{
5327 			const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5328 								   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5329 								   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5330 								   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
5331 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5332 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5333 		}
5334 		/* right, bottom, green quad */
5335 		{
5336 			const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5337 								   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5338 								   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5339 								   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
5340 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5341 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5342 		}
5343 		/* left, top, blue quad */
5344 		{
5345 			const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5346 								   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5347 								   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5348 								   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
5349 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5350 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5351 		}
5352 		/* right, top, yellow quad */
5353 		{
5354 			const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5355 								   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5356 								   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5357 								   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f };
5358 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5359 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5360 		}
5361 
5362 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5363 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * 32 * 4, NULL, GL_STATIC_DRAW);
5364 
5365 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5366 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(float) * 32);
5367 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5368 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 32, sizeof(float) * 32);
5369 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5370 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * sizeof(float) * 32,
5371 							sizeof(float) * 32);
5372 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5373 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * sizeof(float) * 32,
5374 							sizeof(float) * 32);
5375 
5376 		glBindTexture(GL_TEXTURE_2D, m_rt);
5377 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5378 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5379 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5380 		glBindTexture(GL_TEXTURE_2D, 0);
5381 		glViewport(0, 0, 100, 100);
5382 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5383 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5384 
5385 		glGenVertexArrays(1, &m_vertex_array);
5386 
5387 		glUseProgram(m_program);
5388 		glBindVertexArray(m_vertex_array);
5389 
5390 		glClear(GL_COLOR_BUFFER_BIT);
5391 		for (int i = 0; i < 4; ++i)
5392 		{
5393 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5394 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5395 		}
5396 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5397 		{
5398 			return ERROR;
5399 		}
5400 
5401 		glClear(GL_COLOR_BUFFER_BIT);
5402 		for (int i = 0; i < 4; ++i)
5403 		{
5404 			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * sizeof(float) * 32,
5405 							  sizeof(float) * 32);
5406 			glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
5407 		}
5408 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5409 		{
5410 			return ERROR;
5411 		}
5412 
5413 		return NO_ERROR;
5414 	}
5415 
Cleanup()5416 	virtual long Cleanup()
5417 	{
5418 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5419 		glUseProgram(0);
5420 		glDeleteProgram(m_program);
5421 		glDeleteBuffers(5, m_storage_buffer);
5422 		glDeleteVertexArrays(1, &m_vertex_array);
5423 		glDeleteFramebuffers(1, &m_fbo);
5424 		glDeleteTextures(1, &m_rt);
5425 		return NO_ERROR;
5426 	}
5427 };
5428 
5429 class AdvancedSwitchBuffersCS : public ShaderStorageBufferObjectBase
5430 {
5431 	GLuint m_program;
5432 	GLuint m_storage_buffer[6];
5433 
Setup()5434 	virtual long Setup()
5435 	{
5436 		m_program = 0;
5437 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5438 		return NO_ERROR;
5439 	}
5440 
Run()5441 	virtual long Run()
5442 	{
5443 		const char* const glsl_cs =
5444 			NL "layout(local_size_x = 1) in;" NL "layout(binding = 0, std430) buffer Input {" NL "  uint cookie[4];" NL
5445 			   "} g_in;" NL "layout(binding = 1, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL
5446 			   "void main() {" NL "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5447 			   "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5448 			   "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5449 			   "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5450 			   "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5451 		m_program = CreateProgramCS(glsl_cs);
5452 		glLinkProgram(m_program);
5453 		if (!CheckProgram(m_program))
5454 			return ERROR;
5455 
5456 		glGenBuffers(6, m_storage_buffer);
5457 
5458 		const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5459 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5460 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5461 		const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5462 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
5463 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5464 		const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5465 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
5466 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5467 		const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5468 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
5469 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5470 
5471 		GLint alignment;
5472 		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
5473 		GLint offset = static_cast<GLint>(sizeof(data0) > (GLuint)alignment ? sizeof(data0) : alignment);
5474 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
5475 		glBufferData(GL_SHADER_STORAGE_BUFFER, offset * 4, NULL, GL_STATIC_DRAW);
5476 
5477 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[0]);
5478 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, sizeof(data0));
5479 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[1]);
5480 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, offset, sizeof(data0));
5481 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[2]);
5482 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 2 * offset, sizeof(data0));
5483 		glBindBuffer(GL_COPY_READ_BUFFER, m_storage_buffer[3]);
5484 		glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 3 * offset, sizeof(data0));
5485 
5486 		const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5487 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[5]);
5488 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5489 
5490 		glUseProgram(m_program);
5491 		for (int i = 0; i < 4; ++i)
5492 		{
5493 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[i]);
5494 			glDispatchCompute(1, 1, 1);
5495 		}
5496 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5497 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5498 		GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5499 		if (!out_data)
5500 			return ERROR;
5501 		GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5502 		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5503 			out_data[3] != expected[3])
5504 		{
5505 			m_context.getTestContext().getLog()
5506 				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5507 				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5508 				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5509 				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5510 			return ERROR;
5511 		}
5512 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5513 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5514 
5515 		for (int i = 0; i < 4; ++i)
5516 		{
5517 			glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[4], i * offset, sizeof(data0));
5518 			glDispatchCompute(1, 1, 1);
5519 		}
5520 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
5521 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5522 		out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5523 		if (!out_data)
5524 			return ERROR;
5525 		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5526 			out_data[3] != expected[3])
5527 		{
5528 			m_context.getTestContext().getLog()
5529 				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5530 				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5531 				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5532 				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5533 			return ERROR;
5534 		}
5535 
5536 		return NO_ERROR;
5537 	}
5538 
Cleanup()5539 	virtual long Cleanup()
5540 	{
5541 		glUseProgram(0);
5542 		glDeleteProgram(m_program);
5543 		glDeleteBuffers(6, m_storage_buffer);
5544 		return NO_ERROR;
5545 	}
5546 };
5547 //-----------------------------------------------------------------------------
5548 // 2.2 AdvancedSwitchPrograms
5549 //-----------------------------------------------------------------------------
5550 
5551 class AdvancedSwitchPrograms : public ShaderStorageBufferObjectBase
5552 {
5553 	GLuint m_program[4];
5554 	GLuint m_storage_buffer[4];
5555 	GLuint m_vertex_array;
5556 	GLuint m_fbo, m_rt;
5557 
GenSource(int binding)5558 	std::string GenSource(int binding)
5559 	{
5560 		std::stringstream ss;
5561 		ss << NL "struct VertexData {" NL "  vec2 position;" NL "  vec3 color;" NL "};" NL "layout(binding = "
5562 		   << binding << ", std430) buffer Input {" NL "  VertexData vertex[];" NL "} g_vs_in;" NL "out StageData {" NL
5563 						 "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5564 						 "  gl_Position = vec4(g_vs_in.vertex[gl_VertexID].position, 0, 1);" NL
5565 						 "  g_vs_out.color = g_vs_in.vertex[gl_VertexID].color;" NL "}";
5566 		return ss.str();
5567 	}
5568 
Setup()5569 	virtual long Setup()
5570 	{
5571 		memset(m_program, 0, sizeof(m_program));
5572 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5573 		m_vertex_array = 0;
5574 		glGenFramebuffers(1, &m_fbo);
5575 		glGenTextures(1, &m_rt);
5576 		return NO_ERROR;
5577 	}
5578 
Run()5579 	virtual long Run()
5580 	{
5581 		if (!SupportedInVS(1))
5582 			return NOT_SUPPORTED;
5583 
5584 		const char* const glsl_fs =
5585 			NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5586 			   "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5587 		for (int i = 0; i < 4; ++i)
5588 		{
5589 			m_program[i] = CreateProgram(GenSource(i), glsl_fs);
5590 			glLinkProgram(m_program[i]);
5591 			if (!CheckProgram(m_program[i]))
5592 				return ERROR;
5593 		}
5594 
5595 		glGenBuffers(4, m_storage_buffer);
5596 
5597 		/* left, bottom, red quad */
5598 		{
5599 			const float data[] = { -0.4f - 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5600 								   0.4f - 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5601 								   -0.4f - 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
5602 								   0.4f - 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f };
5603 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5604 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5605 		}
5606 		/* right, bottom, green quad */
5607 		{
5608 			const float data[] = { -0.4f + 0.5f, -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5609 								   0.4f + 0.5f,  -0.4f - 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5610 								   -0.4f + 0.5f, 0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
5611 								   0.4f + 0.5f,  0.4f - 0.5f,  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
5612 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5613 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5614 		}
5615 		/* left, top, blue quad */
5616 		{
5617 			const float data[] = { -0.4f - 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5618 								   0.4f - 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5619 								   -0.4f - 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
5620 								   0.4f - 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f };
5621 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5622 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5623 		}
5624 		/* right, top, yellow quad */
5625 		{
5626 			const float data[] = { -0.4f + 0.5f, -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5627 								   0.4f + 0.5f,  -0.4f + 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5628 								   -0.4f + 0.5f, 0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f,
5629 								   0.4f + 0.5f,  0.4f + 0.5f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f };
5630 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5631 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5632 		}
5633 
5634 		glBindTexture(GL_TEXTURE_2D, m_rt);
5635 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5636 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5637 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5638 		glBindTexture(GL_TEXTURE_2D, 0);
5639 		glViewport(0, 0, 100, 100);
5640 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5641 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5642 
5643 		glGenVertexArrays(1, &m_vertex_array);
5644 		glBindVertexArray(m_vertex_array);
5645 
5646 		glClear(GL_COLOR_BUFFER_BIT);
5647 		for (int i = 0; i < 4; ++i)
5648 		{
5649 			glUseProgram(m_program[i]);
5650 			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5651 		}
5652 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5653 		{
5654 			return ERROR;
5655 		}
5656 
5657 		glClear(GL_COLOR_BUFFER_BIT);
5658 		glShaderStorageBlockBinding(m_program[0], 0, 3);
5659 		glUseProgram(m_program[0]);
5660 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5661 		if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(1, 1, 0), vec3(0)))
5662 		{
5663 			return ERROR;
5664 		}
5665 
5666 		glClear(GL_COLOR_BUFFER_BIT);
5667 		glShaderStorageBlockBinding(m_program[3], 0, 0);
5668 		glUseProgram(m_program[3]);
5669 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5670 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0), vec3(0), vec3(0)))
5671 		{
5672 			return ERROR;
5673 		}
5674 
5675 		return NO_ERROR;
5676 	}
5677 
Cleanup()5678 	virtual long Cleanup()
5679 	{
5680 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5681 		glUseProgram(0);
5682 		for (int i = 0; i < 4; ++i)
5683 			glDeleteProgram(m_program[i]);
5684 		glDeleteBuffers(4, m_storage_buffer);
5685 		glDeleteVertexArrays(1, &m_vertex_array);
5686 		glDeleteFramebuffers(1, &m_fbo);
5687 		glDeleteTextures(1, &m_rt);
5688 		return NO_ERROR;
5689 	}
5690 };
5691 
5692 class AdvancedSwitchProgramsCS : public ShaderStorageBufferObjectBase
5693 {
5694 	GLuint m_program[4];
5695 	GLuint m_storage_buffer[5];
5696 
Setup()5697 	virtual long Setup()
5698 	{
5699 		memset(m_program, 0, sizeof(m_program));
5700 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
5701 		return NO_ERROR;
5702 	}
5703 
GenSource(int binding)5704 	std::string GenSource(int binding)
5705 	{
5706 		std::stringstream ss;
5707 		ss << NL "layout(local_size_x = 1) in;" NL "layout(binding = " << binding
5708 		   << ", std430) buffer Input {" NL "  uint cookie[4];" NL "} g_in;" NL
5709 			  "layout(binding = 0, std430) buffer Output {" NL "  uvec4 digest;" NL "} ;" NL "void main() {" NL
5710 			  "  switch (g_in.cookie[0]+g_in.cookie[1]+g_in.cookie[2]+g_in.cookie[3]) {" NL
5711 			  "    case 0x000000ffu: digest.x = 0xff000000u; break;" NL
5712 			  "    case 0x0000ff00u: digest.y = 0x00ff0000u; break;" NL
5713 			  "    case 0x00ff0000u: digest.z = 0x0000ff00u; break;" NL
5714 			  "    case 0xff000000u: digest.w = 0x000000ffu; break;" NL "  }" NL "}";
5715 		return ss.str();
5716 	}
5717 
Run()5718 	virtual long Run()
5719 	{
5720 		for (int i = 0; i < 4; ++i)
5721 		{
5722 			m_program[i] = CreateProgramCS(GenSource(i + 1));
5723 			glLinkProgram(m_program[i]);
5724 			if (!CheckProgram(m_program[i]))
5725 				return ERROR;
5726 		}
5727 
5728 		glGenBuffers(5, m_storage_buffer);
5729 
5730 		const GLubyte data0[] = { 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x88, 0, 0, 0, 0x22 };
5731 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
5732 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data0), data0, GL_STATIC_DRAW);
5733 		const GLubyte data1[] = { 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0 };
5734 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
5735 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data1), data1, GL_STATIC_DRAW);
5736 		const GLubyte data2[] = { 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0, 0x22, 0, 0 };
5737 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
5738 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data2), data2, GL_STATIC_DRAW);
5739 		const GLubyte data3[] = { 0x22, 0, 0, 0, 0x88, 0, 0, 0, 0x11, 0, 0, 0, 0x44, 0, 0, 0 };
5740 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
5741 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data3), data3, GL_STATIC_DRAW);
5742 
5743 		const GLubyte data[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
5744 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
5745 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5746 
5747 		for (int i = 0; i < 4; ++i)
5748 		{
5749 			glUseProgram(m_program[i]);
5750 			glDispatchCompute(1, 1, 1);
5751 		}
5752 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
5753 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5754 		GLuint* out_data = (GLuint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data0), GL_MAP_READ_BIT);
5755 		if (!out_data)
5756 			return ERROR;
5757 		GLuint expected[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
5758 		if (out_data[0] != expected[0] || out_data[1] != expected[1] || out_data[2] != expected[2] ||
5759 			out_data[3] != expected[3])
5760 		{
5761 			m_context.getTestContext().getLog()
5762 				<< tcu::TestLog::Message << "Received: " << tcu::toHex(out_data[0]) << ", " << tcu::toHex(out_data[1])
5763 				<< ", " << tcu::toHex(out_data[2]) << ", " << tcu::toHex(out_data[3])
5764 				<< ", but expected: " << tcu::toHex(expected[0]) << ", " << tcu::toHex(expected[1]) << ", "
5765 				<< tcu::toHex(expected[2]) << ", " << tcu::toHex(expected[3]) << tcu::TestLog::EndMessage;
5766 			return ERROR;
5767 		}
5768 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
5769 
5770 		return NO_ERROR;
5771 	}
5772 
Cleanup()5773 	virtual long Cleanup()
5774 	{
5775 		glUseProgram(0);
5776 		for (int i = 0; i < 4; ++i)
5777 			glDeleteProgram(m_program[i]);
5778 		glDeleteBuffers(5, m_storage_buffer);
5779 		return NO_ERROR;
5780 	}
5781 };
5782 //-----------------------------------------------------------------------------
5783 // 2.3.1 AdvancedWriteFragment
5784 //-----------------------------------------------------------------------------
5785 
5786 class AdvancedWriteFragment : public ShaderStorageBufferObjectBase
5787 {
5788 	GLuint m_program[2];
5789 	GLuint m_storage_buffer;
5790 	GLuint m_counter_buffer;
5791 	GLuint m_attribless_vertex_array;
5792 	GLuint m_draw_vertex_array;
5793 	GLuint m_fbo, m_rt;
5794 
Setup()5795 	virtual long Setup()
5796 	{
5797 		memset(m_program, 0, sizeof(m_program));
5798 		m_storage_buffer		  = 0;
5799 		m_counter_buffer		  = 0;
5800 		m_attribless_vertex_array = 0;
5801 		m_draw_vertex_array		  = 0;
5802 		glGenFramebuffers(1, &m_fbo);
5803 		glGenTextures(1, &m_rt);
5804 		return NO_ERROR;
5805 	}
5806 
Run()5807 	virtual long Run()
5808 	{
5809 		const char* const glsl_vs0 = NL
5810 			"out StageData {" NL "  vec2 position;" NL "  vec3 color;" NL "} g_vs_out;" NL
5811 			"const 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
5812 			"const 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
5813 			"const vec3 g_color[4] = vec3[4](vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0));" NL
5814 			"void main() {" NL "  vec2 pos = g_quad[gl_VertexID] + g_offset[gl_InstanceID];" NL
5815 			"  gl_Position = vec4(pos, 0, 1);" NL "  g_vs_out.position = pos;" NL
5816 			"  g_vs_out.color = g_color[gl_InstanceID];" NL "}";
5817 
5818 		const char* const glsl_fs0 =
5819 			NL "in StageData {" NL "  vec2 position;" NL "  vec3 color;" NL "} g_fs_in;" NL
5820 			   "layout(location = 0) out vec4 g_fs_out;" NL "struct FragmentData {" NL "  vec2 position;" NL
5821 			   "  vec3 color;" NL "};" NL "layout(std430, binding = 3) buffer Output {" NL
5822 			   "  FragmentData g_fragment[];" NL "};" NL "uniform uint g_max_fragment_count = 100 * 100;" NL
5823 			   "layout(binding = 2, offset = 0) uniform atomic_uint g_fragment_counter;" NL "void main() {" NL
5824 			   "  uint fragment_number = atomicCounterIncrement(g_fragment_counter);" NL
5825 			   "  if (fragment_number < g_max_fragment_count) {" NL
5826 			   "    g_fragment[fragment_number].position = g_fs_in.position;" NL
5827 			   "    g_fragment[fragment_number].color = g_fs_in.color;" NL "  }" NL
5828 			   "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5829 
5830 		m_program[0] = CreateProgram(glsl_vs0, glsl_fs0);
5831 		glLinkProgram(m_program[0]);
5832 		if (!CheckProgram(m_program[0]))
5833 			return ERROR;
5834 
5835 		const char* const glsl_vs1 =
5836 			NL "layout(location = 0) in vec4 g_in_position;" NL "layout(location = 1) in vec4 g_in_color;" NL
5837 			   "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
5838 			   "  gl_Position = vec4(g_in_position.xy, 0, 1);" NL "  g_vs_out.color = g_in_color.rgb;" NL "}";
5839 
5840 		const char* const glsl_fs1 =
5841 			NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
5842 			   "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
5843 
5844 		m_program[1] = CreateProgram(glsl_vs1, glsl_fs1);
5845 		glLinkProgram(m_program[1]);
5846 		if (!CheckProgram(m_program[1]))
5847 			return ERROR;
5848 
5849 		// The first pass renders four squares on-screen, and writes a
5850 		// record to the SSBO for each fragment processed.  The rectangles
5851 		// will be 40x40 when using a 100x100 viewport, so we expect 1600
5852 		// pixels per rectangle or 6400 pixels total.  Size the SSBO
5853 		// accordingly, and render the second pass (sourcing the SSBO as a
5854 		// vertex buffer) with an identical number of points.  If we have
5855 		// a larger buffer and draw more points on the second pass, those
5856 		// may overwrite "real" points using garbage position/color.
5857 		int expectedPixels = 6400;
5858 
5859 		glGenBuffers(1, &m_storage_buffer);
5860 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer);
5861 		glBufferData(GL_SHADER_STORAGE_BUFFER, expectedPixels * 32, NULL, GL_DYNAMIC_DRAW);
5862 
5863 		glGenBuffers(1, &m_counter_buffer);
5864 		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
5865 		glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
5866 		uvec4 zero(0);
5867 		glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
5868 
5869 		glBindTexture(GL_TEXTURE_2D, m_rt);
5870 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5871 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5872 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
5873 		glBindTexture(GL_TEXTURE_2D, 0);
5874 		glViewport(0, 0, 100, 100);
5875 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
5876 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
5877 
5878 		glGenVertexArrays(1, &m_attribless_vertex_array);
5879 
5880 		glGenVertexArrays(1, &m_draw_vertex_array);
5881 		glBindVertexArray(m_draw_vertex_array);
5882 		glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
5883 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, 0);
5884 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void*>(16));
5885 		glBindBuffer(GL_ARRAY_BUFFER, 0);
5886 		glEnableVertexAttribArray(0);
5887 		glEnableVertexAttribArray(1);
5888 		glBindVertexArray(0);
5889 
5890 		glClear(GL_COLOR_BUFFER_BIT);
5891 		glUseProgram(m_program[0]);
5892 		glUniform1ui(glGetUniformLocation(m_program[0], "g_max_fragment_count"), expectedPixels);
5893 		glBindVertexArray(m_attribless_vertex_array);
5894 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
5895 
5896 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
5897 		{
5898 			return ERROR;
5899 		}
5900 
5901 		glClear(GL_COLOR_BUFFER_BIT);
5902 		glUseProgram(m_program[1]);
5903 		glBindVertexArray(m_draw_vertex_array);
5904 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
5905 		glDrawArrays(GL_POINTS, 0, expectedPixels);
5906 		int bad_pixels;
5907 
5908 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1), &bad_pixels) &&
5909 			bad_pixels > 2)
5910 		{
5911 			return ERROR;
5912 		}
5913 
5914 		return NO_ERROR;
5915 	}
5916 
Cleanup()5917 	virtual long Cleanup()
5918 	{
5919 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5920 		glUseProgram(0);
5921 		for (int i = 0; i < 2; ++i)
5922 			glDeleteProgram(m_program[i]);
5923 		glDeleteBuffers(1, &m_storage_buffer);
5924 		glDeleteBuffers(1, &m_counter_buffer);
5925 		glDeleteVertexArrays(1, &m_attribless_vertex_array);
5926 		glDeleteVertexArrays(1, &m_draw_vertex_array);
5927 		glDeleteFramebuffers(1, &m_fbo);
5928 		glDeleteTextures(1, &m_rt);
5929 		return NO_ERROR;
5930 	}
5931 };
5932 
5933 //-----------------------------------------------------------------------------
5934 // 2.3.2 AdvancedWriteGeometry
5935 //-----------------------------------------------------------------------------
5936 class AdvancedWriteGeometry : public ShaderStorageBufferObjectBase
5937 {
5938 	GLuint m_program[2];
5939 	GLuint m_storage_buffer;
5940 	GLuint m_vertex_array[2];
5941 	GLuint m_vertex_buffer;
5942 
Setup()5943 	virtual long Setup()
5944 	{
5945 		memset(m_program, 0, sizeof(m_program));
5946 		m_storage_buffer = 0;
5947 		memset(m_vertex_array, 0, sizeof(m_vertex_array));
5948 		m_vertex_buffer = 0;
5949 		return NO_ERROR;
5950 	}
5951 
Run()5952 	virtual long Run()
5953 	{
5954 		if (!SupportedInGS(1))
5955 			return NOT_SUPPORTED;
5956 
5957 		const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
5958 									   "  gl_Position = g_in_position;" NL "}";
5959 
5960 		const char* const glsl_gs =
5961 			NL "layout(triangles) in;" NL "layout(triangle_strip, max_vertices = 3) out;" NL
5962 			   "layout(std430, binding = 1) buffer OutputBuffer {" NL "  vec4 g_output_buffer[];" NL "};" NL
5963 			   "void main() {" NL "  for (int i = 0; i < 3; ++i) {" NL
5964 			   "    const int idx = gl_PrimitiveIDIn * 3 + i;" NL "    g_output_buffer[idx] = gl_in[i].gl_Position;" NL
5965 			   "    gl_Position = g_output_buffer[idx];" NL "    EmitVertex();" NL "  }" NL "}";
5966 
5967 		const char* const glsl_fs =
5968 			NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
5969 
5970 		m_program[0] = CreateProgram(glsl_vs, "", "", glsl_gs, glsl_fs);
5971 		glLinkProgram(m_program[0]);
5972 		if (!CheckProgram(m_program[0]))
5973 			return ERROR;
5974 
5975 		m_program[1] = CreateProgram(glsl_vs, glsl_fs);
5976 		glLinkProgram(m_program[1]);
5977 		if (!CheckProgram(m_program[1]))
5978 			return ERROR;
5979 
5980 		/* vertex buffer */
5981 		{
5982 			const float data[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
5983 			glGenBuffers(1, &m_vertex_buffer);
5984 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5985 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
5986 			glBindBuffer(GL_ARRAY_BUFFER, 0);
5987 		}
5988 
5989 		glGenBuffers(1, &m_storage_buffer);
5990 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer);
5991 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
5992 
5993 		glGenVertexArrays(2, m_vertex_array);
5994 
5995 		glBindVertexArray(m_vertex_array[0]);
5996 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
5997 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5998 		glBindBuffer(GL_ARRAY_BUFFER, 0);
5999 		glEnableVertexAttribArray(0);
6000 		glBindVertexArray(0);
6001 
6002 		glBindVertexArray(m_vertex_array[1]);
6003 		glBindBuffer(GL_ARRAY_BUFFER, m_storage_buffer);
6004 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
6005 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6006 		glEnableVertexAttribArray(0);
6007 		glBindVertexArray(0);
6008 
6009 		glClear(GL_COLOR_BUFFER_BIT);
6010 		glUseProgram(m_program[0]);
6011 		glBindVertexArray(m_vertex_array[0]);
6012 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6013 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6014 		{
6015 			return ERROR;
6016 		}
6017 
6018 		glClear(GL_COLOR_BUFFER_BIT);
6019 		glUseProgram(m_program[1]);
6020 		glBindVertexArray(m_vertex_array[1]);
6021 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
6022 		glDrawArrays(GL_TRIANGLES, 0, 6);
6023 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6024 		{
6025 			return ERROR;
6026 		}
6027 
6028 		return NO_ERROR;
6029 	}
6030 
Cleanup()6031 	virtual long Cleanup()
6032 	{
6033 		glUseProgram(0);
6034 		for (int i = 0; i < 2; ++i)
6035 			glDeleteProgram(m_program[i]);
6036 		glDeleteBuffers(1, &m_storage_buffer);
6037 		glDeleteBuffers(1, &m_vertex_buffer);
6038 		glDeleteVertexArrays(2, m_vertex_array);
6039 		return NO_ERROR;
6040 	}
6041 };
6042 //-----------------------------------------------------------------------------
6043 // 2.3.3 AdvancedWriteTessellation
6044 //-----------------------------------------------------------------------------
6045 
6046 class AdvancedWriteTessellation : public ShaderStorageBufferObjectBase
6047 {
6048 	GLuint m_program;
6049 	GLuint m_storage_buffer;
6050 	GLuint m_counter_buffer;
6051 	GLuint m_vertex_array;
6052 	GLuint m_vertex_buffer;
6053 
Setup()6054 	virtual long Setup()
6055 	{
6056 		m_program		 = 0;
6057 		m_storage_buffer = 0;
6058 		m_counter_buffer = 0;
6059 		m_vertex_array   = 0;
6060 		m_vertex_buffer  = 0;
6061 		return NO_ERROR;
6062 	}
6063 
Run()6064 	virtual long Run()
6065 	{
6066 		if (!SupportedInTES(1))
6067 			return NOT_SUPPORTED;
6068 
6069 		const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "void main() {" NL
6070 									   "  gl_Position = g_in_position;" NL "}";
6071 
6072 		const char* const glsl_tes =
6073 			NL "layout(quads) in;" NL "struct VertexData {" NL "  int valid;" NL "  vec4 position;" NL "};" NL
6074 			   "layout(std430, binding = 2) buffer VertexBuffer {" NL "  VertexData g_vertex_buffer[];" NL "};" NL
6075 			   "layout(binding = 2, offset = 0) uniform atomic_uint g_vertex_counter;" NL "void main() {" NL
6076 			   "  const uint idx = atomicCounterIncrement(g_vertex_counter);" NL
6077 			   "  vec4 p0 = mix(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_TessCoord.x);" NL
6078 			   "  vec4 p1 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x);" NL
6079 			   "  vec4 p = mix(p0, p1, gl_TessCoord.y);" NL "  g_vertex_buffer[idx].position = p;" NL
6080 			   "  g_vertex_buffer[idx].valid = 1;" NL "  gl_Position = g_vertex_buffer[idx].position;" NL "}";
6081 
6082 		const char* const glsl_fs =
6083 			NL "layout(location = 0) out vec4 g_fs_out;" NL "void main() {" NL "  g_fs_out = vec4(0, 1, 0, 1);" NL "}";
6084 
6085 		m_program = CreateProgram(glsl_vs, "", glsl_tes, "", glsl_fs);
6086 		glLinkProgram(m_program);
6087 		if (!CheckProgram(m_program))
6088 			return ERROR;
6089 
6090 		/* vertex buffer */
6091 		{
6092 			const float data[] = { -1, -1, 1, -1, 1, 1, -1, 1 };
6093 			glGenBuffers(1, &m_vertex_buffer);
6094 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6095 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6096 			glBindBuffer(GL_ARRAY_BUFFER, 0);
6097 		}
6098 
6099 		glGenBuffers(1, &m_counter_buffer);
6100 		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 2, m_counter_buffer);
6101 		glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
6102 		uvec4 zero;
6103 		glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 4, &zero);
6104 
6105 		struct
6106 		{
6107 			int  valid;
6108 			int  pad[3];
6109 			vec4 position;
6110 		} data[6];
6111 		deMemset((void *)data, 0, sizeof(data));
6112 		glGenBuffers(1, &m_storage_buffer);
6113 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer);
6114 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6115 
6116 		glGenVertexArrays(1, &m_vertex_array);
6117 		glBindVertexArray(m_vertex_array);
6118 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6119 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6120 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6121 		glEnableVertexAttribArray(0);
6122 		glBindVertexArray(0);
6123 
6124 		glClear(GL_COLOR_BUFFER_BIT);
6125 		glUseProgram(m_program);
6126 		glBindVertexArray(m_vertex_array);
6127 		glPatchParameteri(GL_PATCH_VERTICES, 4);
6128 		glDrawArrays(GL_PATCHES, 0, 4);
6129 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6130 		{
6131 			return ERROR;
6132 		}
6133 
6134 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6135 		glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6136 		for (int i = 0; i < 4; ++i)
6137 		{
6138 			vec4 p = data[i].position;
6139 			if (p[2] != 0.0f || p[3] != 1.0f)
6140 				return ERROR;
6141 			if (data[i].valid != 1)
6142 				return ERROR;
6143 		}
6144 
6145 		return NO_ERROR;
6146 	}
6147 
Cleanup()6148 	virtual long Cleanup()
6149 	{
6150 		glPatchParameteri(GL_PATCH_VERTICES, 3);
6151 		glUseProgram(0);
6152 		glDeleteProgram(m_program);
6153 		glDeleteBuffers(1, &m_storage_buffer);
6154 		glDeleteBuffers(1, &m_counter_buffer);
6155 		glDeleteBuffers(1, &m_vertex_buffer);
6156 		glDeleteVertexArrays(1, &m_vertex_array);
6157 		return NO_ERROR;
6158 	}
6159 };
6160 
6161 //-----------------------------------------------------------------------------
6162 // 2.4.1 AdvancedIndirectAddressingCase1
6163 //-----------------------------------------------------------------------------
6164 class AdvancedIndirectAddressingCase1 : public ShaderStorageBufferObjectBase
6165 {
6166 	GLuint m_program;
6167 	GLuint m_storage_buffer[4];
6168 	GLuint m_vertex_array;
6169 	GLuint m_vertex_buffer;
6170 	GLuint m_fbo, m_rt;
6171 
Setup()6172 	virtual long Setup()
6173 	{
6174 		m_program = 0;
6175 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6176 		m_vertex_array  = 0;
6177 		m_vertex_buffer = 0;
6178 		glGenFramebuffers(1, &m_fbo);
6179 		glGenTextures(1, &m_rt);
6180 		return NO_ERROR;
6181 	}
6182 
Run()6183 	virtual long Run()
6184 	{
6185 		if (!SupportedInVS(4))
6186 			return NOT_SUPPORTED;
6187 
6188 		const char* const glsl_vs =
6189 			NL "layout(location = 0) in vec2 g_in_position;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
6190 			   "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
6191 			   "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
6192 			   "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
6193 			   "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
6194 			   "out StageData {" NL "  vec3 color;" NL "} g_vs_out;" NL "void main() {" NL
6195 			   "  const uint mid = g_material_id[gl_InstanceID];" NL "  Material m = g_material[mid];" NL
6196 			   "  const uint tid = g_transform_id[gl_InstanceID];" NL "  vec2 t = g_transform.translation[tid];" NL
6197 			   "  gl_Position = vec4(g_in_position + t, 0, 1);" NL "  g_vs_out.color = m.color;" NL "}";
6198 
6199 		const char* const glsl_fs =
6200 			NL "in StageData {" NL "  vec3 color;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
6201 			   "void main() {" NL "  g_fs_out = vec4(g_fs_in.color, 1);" NL "}";
6202 
6203 		m_program = CreateProgram(glsl_vs, glsl_fs);
6204 		glLinkProgram(m_program);
6205 		if (!CheckProgram(m_program))
6206 			return ERROR;
6207 
6208 		glGenBuffers(4, m_storage_buffer);
6209 
6210 		/* material buffer */
6211 		{
6212 			const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6213 								   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
6214 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6215 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6216 		}
6217 		/* material id buffer */
6218 		{
6219 			const unsigned int data[] = { 2, 3, 0, 2 };
6220 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6221 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6222 		}
6223 		/* transform buffer */
6224 		{
6225 			const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
6226 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6227 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6228 		}
6229 		/* transform id buffer */
6230 		{
6231 			const unsigned int data[] = { 3, 1, 0, 2 };
6232 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6233 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6234 		}
6235 
6236 		/* vertex buffer */
6237 		{
6238 			const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
6239 			glGenBuffers(1, &m_vertex_buffer);
6240 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6241 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6242 			glBindBuffer(GL_ARRAY_BUFFER, 0);
6243 		}
6244 
6245 		glBindTexture(GL_TEXTURE_2D, m_rt);
6246 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6247 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6248 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6249 		glBindTexture(GL_TEXTURE_2D, 0);
6250 		glViewport(0, 0, 100, 100);
6251 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6252 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6253 
6254 		glGenVertexArrays(1, &m_vertex_array);
6255 		glBindVertexArray(m_vertex_array);
6256 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6257 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6258 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6259 		glEnableVertexAttribArray(0);
6260 		glBindVertexArray(0);
6261 
6262 		glClear(GL_COLOR_BUFFER_BIT);
6263 		glUseProgram(m_program);
6264 		glBindVertexArray(m_vertex_array);
6265 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6266 
6267 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(1, 1, 0), vec3(0, 0, 1), vec3(0, 0, 1)))
6268 		{
6269 			return ERROR;
6270 		}
6271 
6272 		/* update material id buffer with BufferSubData */
6273 		{
6274 			const unsigned int data[] = { 3, 2, 1, 0 };
6275 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6276 			glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6277 		}
6278 
6279 		/* update transform id buffer with BufferData */
6280 		{
6281 			const unsigned int data[] = { 0, 1, 2, 3 };
6282 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6283 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6284 		}
6285 
6286 		glClear(GL_COLOR_BUFFER_BIT);
6287 		glUseProgram(m_program);
6288 		glBindVertexArray(m_vertex_array);
6289 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
6290 		if (!ValidateWindow4Quads(vec3(1, 1, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0)))
6291 		{
6292 			return ERROR;
6293 		}
6294 
6295 		return NO_ERROR;
6296 	}
6297 
Cleanup()6298 	virtual long Cleanup()
6299 	{
6300 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6301 		glUseProgram(0);
6302 		glDeleteProgram(m_program);
6303 		glDeleteBuffers(4, m_storage_buffer);
6304 		glDeleteBuffers(1, &m_vertex_buffer);
6305 		glDeleteVertexArrays(1, &m_vertex_array);
6306 		glDeleteFramebuffers(1, &m_fbo);
6307 		glDeleteTextures(1, &m_rt);
6308 		return NO_ERROR;
6309 	}
6310 };
6311 
6312 class AdvancedIndirectAddressingCase1CS : public ShaderStorageBufferObjectBase
6313 {
6314 	GLuint m_program;
6315 	GLuint m_storage_buffer[5];
6316 
Setup()6317 	virtual long Setup()
6318 	{
6319 		m_program = 0;
6320 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6321 		return NO_ERROR;
6322 	}
6323 
Run()6324 	virtual long Run()
6325 	{
6326 		bool status = true;
6327 
6328 		const char* const glsl_cs =
6329 			NL "layout(local_size_x = 2, local_size_y = 2) in;" NL "struct Material {" NL "  vec3 color;" NL "};" NL
6330 			   "layout(binding = 0, std430) buffer MaterialBuffer {" NL "  Material g_material[4];" NL "};" NL
6331 			   "layout(binding = 1, std430) buffer MaterialIDBuffer {" NL "  uint g_material_id[4];" NL "};" NL
6332 			   "layout(binding = 2, std430) buffer TransformBuffer {" NL "  vec2 translation[4];" NL "} g_transform;" NL
6333 			   "layout(binding = 3, std430) buffer TransformIDBuffer {" NL "  uint g_transform_id[4];" NL "};" NL
6334 			   "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[16];" NL "  vec2 pos[16];" NL
6335 			   "};" NL "vec2 g_in_position[4] = vec2[4](vec2(-0.4f, -0.4f), vec2(0.4f, -0.4f), vec2(-0.4f, 0.4f), "
6336 			   "vec2(0.4f, 0.4f));" NL "void main() {" NL "  uint mid = g_material_id[gl_WorkGroupID.x];" NL
6337 			   "  Material m = g_material[mid];" NL "  uint tid = g_transform_id[gl_WorkGroupID.x];" NL
6338 			   "  vec2 t = g_transform.translation[tid];" NL
6339 			   "  pos[gl_LocalInvocationIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x * gl_WorkGroupSize.y] " NL
6340 			   "    = g_in_position[gl_LocalInvocationIndex] + t;" NL "  color[gl_LocalInvocationIndex + "
6341 			   "gl_WorkGroupID.x * gl_WorkGroupSize.x * "
6342 			   "gl_WorkGroupSize.y] = m.color;" NL "}";
6343 
6344 		m_program = CreateProgramCS(glsl_cs);
6345 		glLinkProgram(m_program);
6346 		if (!CheckProgram(m_program))
6347 			return ERROR;
6348 
6349 		glGenBuffers(5, m_storage_buffer);
6350 
6351 		/* material buffer */
6352 		{
6353 			const float data[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
6354 								   0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
6355 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
6356 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6357 		}
6358 		/* material id buffer */
6359 		{
6360 			const unsigned int data[] = { 2, 3, 0, 2 };
6361 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
6362 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6363 		}
6364 		/* transform buffer */
6365 		{
6366 			const float data[] = { -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f };
6367 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
6368 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6369 		}
6370 		/* transform id buffer */
6371 		{
6372 			const unsigned int data[] = { 3, 1, 0, 2 };
6373 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
6374 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6375 		}
6376 
6377 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6378 		glBufferData(GL_SHADER_STORAGE_BUFFER, 16 * 4 * 4 + 16 * 2 * 4, 0, GL_STATIC_DRAW);
6379 
6380 		glUseProgram(m_program);
6381 		glDispatchCompute(4, 1, 1);
6382 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6383 		GLfloat* out_data =
6384 			(GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6385 		if (!out_data)
6386 			return ERROR;
6387 		GLfloat expected[16 * 4 + 16 * 2] = {
6388 			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,
6389 			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,
6390 			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,
6391 			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,
6392 			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,
6393 			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,
6394 			-0.9f, -0.1f, -0.1f, -0.1f, -0.9f, 0.1f,  -0.1f, 0.1f,  -0.9f, 0.9f,  -0.1f, 0.9f
6395 		};
6396 		for (int i = 0; i < 16; ++i)
6397 		{
6398 			if (out_data[i * 4 + 0] != expected[i * 4 + 0] || out_data[i * 4 + 1] != expected[i * 4 + 1] ||
6399 				out_data[i * 4 + 2] != expected[i * 4 + 2])
6400 			{
6401 				m_context.getTestContext().getLog()
6402 					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6403 					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[i * 4 + 0] << ", "
6404 					<< expected[i * 4 + 1] << ", " << expected[i * 4 + 2] << tcu::TestLog::EndMessage;
6405 				status = false;
6406 			}
6407 		}
6408 		for (int i = 32; i < 32 + 16; ++i)
6409 		{
6410 			if (fabs(out_data[i * 2 + 0] - expected[i * 2 + 0]) > 1e-6 ||
6411 				fabs(out_data[i * 2 + 1] - expected[i * 2 + 1]) > 1e-6)
6412 			{
6413 				m_context.getTestContext().getLog()
6414 					<< tcu::TestLog::Message << "Received: " << out_data[i * 2 + 0] << ", " << out_data[i * 2 + 1]
6415 					<< ", but expected: " << expected[i * 2 + 0] << ", " << expected[i * 2 + 1]
6416 					<< tcu::TestLog::EndMessage;
6417 				status = false;
6418 			}
6419 		}
6420 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6421 
6422 		/* update material id buffer with BufferSubData */
6423 		{
6424 			const unsigned int data[] = { 3, 2, 1, 0 };
6425 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
6426 			glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
6427 		}
6428 
6429 		/* update transform id buffer with BufferData */
6430 		{
6431 			const unsigned int data[] = { 0, 1, 2, 3 };
6432 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
6433 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
6434 		}
6435 
6436 		glUseProgram(m_program);
6437 		glDispatchCompute(4, 1, 1);
6438 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6439 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6440 		GLfloat* out_data2 =
6441 			(GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16 * 4 * 4 + 16 * 2 * 4, GL_MAP_READ_BIT);
6442 		if (!out_data2)
6443 			return ERROR;
6444 		GLfloat expected2[16 * 4 + 16 * 2] = {
6445 			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,
6446 			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,
6447 			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,
6448 			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,
6449 			-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,
6450 			-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
6451 		};
6452 		for (int i = 0; i < 16; ++i)
6453 		{
6454 			if (out_data2[i * 4 + 0] != expected2[i * 4 + 0] || out_data2[i * 4 + 1] != expected2[i * 4 + 1] ||
6455 				out_data2[i * 4 + 2] != expected2[i * 4 + 2])
6456 			{
6457 				m_context.getTestContext().getLog()
6458 					<< tcu::TestLog::Message << "Received: " << out_data2[i * 4 + 0] << ", " << out_data2[i * 4 + 1]
6459 					<< ", " << out_data2[i * 4 + 2] << ", but expected: " << expected2[i * 4 + 0] << ", "
6460 					<< expected2[i * 4 + 1] << ", " << expected2[i * 4 + 2] << tcu::TestLog::EndMessage;
6461 				status = false;
6462 			}
6463 		}
6464 		for (int i = 32; i < 32 + 16; ++i)
6465 		{
6466 			if (fabs(out_data2[i * 2 + 0] - expected2[i * 2 + 0]) > 1e-6 ||
6467 				fabs(out_data2[i * 2 + 1] - expected2[i * 2 + 1]) > 1e-6)
6468 			{
6469 				m_context.getTestContext().getLog()
6470 					<< tcu::TestLog::Message << "Received: " << out_data2[i * 2 + 0] << ", " << out_data2[i * 2 + 1]
6471 					<< ", but expected: " << expected2[i * 2 + 0] << ", " << expected2[i * 2 + 1]
6472 					<< tcu::TestLog::EndMessage;
6473 				status = false;
6474 			}
6475 		}
6476 
6477 		if (status)
6478 			return NO_ERROR;
6479 		else
6480 			return ERROR;
6481 	}
6482 
Cleanup()6483 	virtual long Cleanup()
6484 	{
6485 		glUseProgram(0);
6486 		glDeleteProgram(m_program);
6487 		glDeleteBuffers(5, m_storage_buffer);
6488 		return NO_ERROR;
6489 	}
6490 };
6491 //-----------------------------------------------------------------------------
6492 // 2.4.2 AdvancedIndirectAddressingCase2
6493 //-----------------------------------------------------------------------------
6494 
6495 class AdvancedIndirectAddressingCase2 : public ShaderStorageBufferObjectBase
6496 {
6497 	GLuint m_program;
6498 	GLuint m_storage_buffer[8];
6499 	GLuint m_vertex_array;
6500 	GLuint m_vertex_buffer;
6501 	GLuint m_fbo, m_rt;
6502 
Setup()6503 	virtual long Setup()
6504 	{
6505 		m_program = 0;
6506 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6507 		m_vertex_array  = 0;
6508 		m_vertex_buffer = 0;
6509 		glGenFramebuffers(1, &m_fbo);
6510 		glGenTextures(1, &m_rt);
6511 		return NO_ERROR;
6512 	}
6513 
Run()6514 	virtual long Run()
6515 	{
6516 		if (!SupportedInVS(4))
6517 			return NOT_SUPPORTED;
6518 
6519 		const char* const glsl_vs =
6520 			NL "layout(location = 1) in vec2 g_in_position;" NL "layout(binding = 0, std430) buffer Transform {" NL
6521 			   "  vec2 translation;" NL "} g_transform[4];" NL "uniform uint g_transform_id = 2;" NL "void main() {" NL
6522 			   "  gl_Position = vec4(g_in_position + g_transform[g_transform_id].translation, 0, 1);" NL "}";
6523 
6524 		const char* const glsl_fs =
6525 			NL "layout(location = 0) out vec4 g_fs_out;" NL "layout(binding = 4, std430) buffer Material {" NL
6526 			   "  vec3 color;" NL "} g_material[4];" NL "uniform int g_material_id = 1;" NL "void main() {" NL
6527 			   "  g_fs_out = vec4(g_material[g_material_id].color, 1);" NL "}";
6528 		m_program = CreateProgram(glsl_vs, glsl_fs);
6529 		glLinkProgram(m_program);
6530 		if (!CheckProgram(m_program))
6531 			return ERROR;
6532 
6533 		glGenBuffers(8, m_storage_buffer);
6534 
6535 		/* transform buffers */
6536 		{
6537 			const float data[4][2] = { { -0.5f, -0.5f }, { 0.5f, -0.5f }, { -0.5f, 0.5f }, { 0.5f, 0.5f } };
6538 
6539 			for (GLuint i = 0; i < 4; ++i)
6540 			{
6541 				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6542 				glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6543 			}
6544 		}
6545 		/* material buffers */
6546 		{
6547 			const float data[4][4] = { { 1.0f, 0.0f, 0.0f, 0.0f },
6548 									   { 0.0f, 1.0f, 0.0f, 0.0f },
6549 									   { 0.0f, 0.0f, 1.0f, 0.0f },
6550 									   { 1.0f, 1.0f, 0.0f, 0.0f } };
6551 			for (GLuint i = 0; i < 4; ++i)
6552 			{
6553 				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i + 4, m_storage_buffer[i + 4]);
6554 				glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6555 			}
6556 		}
6557 
6558 		/* vertex buffer */
6559 		{
6560 			const float data[] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
6561 			glGenBuffers(1, &m_vertex_buffer);
6562 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6563 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6564 			glBindBuffer(GL_ARRAY_BUFFER, 0);
6565 		}
6566 
6567 		glBindTexture(GL_TEXTURE_2D, m_rt);
6568 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6569 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
6570 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
6571 		glBindTexture(GL_TEXTURE_2D, 0);
6572 		glViewport(0, 0, 100, 100);
6573 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
6574 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
6575 
6576 		glGenVertexArrays(1, &m_vertex_array);
6577 		glBindVertexArray(m_vertex_array);
6578 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6579 		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
6580 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6581 		glEnableVertexAttribArray(1);
6582 		glBindVertexArray(0);
6583 
6584 		glUseProgram(m_program);
6585 		glBindVertexArray(m_vertex_array);
6586 
6587 		glClear(GL_COLOR_BUFFER_BIT);
6588 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6589 		if (!ValidateWindow4Quads(vec3(0), vec3(0), vec3(0), vec3(0, 1, 0)))
6590 		{
6591 			return ERROR;
6592 		}
6593 
6594 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6595 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6596 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6597 		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(0), vec3(0), vec3(0, 1, 0)))
6598 		{
6599 			return ERROR;
6600 		}
6601 
6602 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6603 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6604 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
6605 		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(0), vec3(0, 1, 0)))
6606 		{
6607 			return ERROR;
6608 		}
6609 
6610 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6611 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6612 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6613 		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 0, 0), vec3(0, 1, 0)))
6614 		{
6615 			return ERROR;
6616 		}
6617 
6618 		// once again with only one validation at the end
6619 		glClear(GL_COLOR_BUFFER_BIT);
6620 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 2);
6621 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6622 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6623 
6624 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 0);
6625 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 2);
6626 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6627 
6628 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 1);
6629 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6630 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6631 
6632 		glUniform1ui(glGetUniformLocation(m_program, "g_transform_id"), 3);
6633 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 0);
6634 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[7]);
6635 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6636 
6637 		if (!ValidateWindow4Quads(vec3(0, 0, 1), vec3(1, 1, 0), vec3(1, 1, 0), vec3(0, 1, 0)))
6638 		{
6639 			return ERROR;
6640 		}
6641 		return NO_ERROR;
6642 	}
6643 
Cleanup()6644 	virtual long Cleanup()
6645 	{
6646 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6647 		glUseProgram(0);
6648 		glDeleteProgram(m_program);
6649 		glDeleteBuffers(8, m_storage_buffer);
6650 		glDeleteBuffers(1, &m_vertex_buffer);
6651 		glDeleteVertexArrays(1, &m_vertex_array);
6652 		glDeleteFramebuffers(1, &m_fbo);
6653 		glDeleteTextures(1, &m_rt);
6654 		return NO_ERROR;
6655 	}
6656 };
6657 
6658 class AdvancedIndirectAddressingCase2CS : public ShaderStorageBufferObjectBase
6659 {
6660 	GLuint m_program;
6661 	GLuint m_storage_buffer[5];
6662 
Setup()6663 	virtual long Setup()
6664 	{
6665 		m_program = 0;
6666 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6667 		return NO_ERROR;
6668 	}
6669 
Run()6670 	virtual long Run()
6671 	{
6672 		GLint blocksC;
6673 		glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &blocksC);
6674 		if (blocksC < 8)
6675 			return NOT_SUPPORTED;
6676 		bool status = true;
6677 
6678 		const char* const glsl_cs =
6679 			NL "layout(local_size_x = 4) in;" NL "layout(binding = 0, std430) buffer Material {" NL "  vec3 color;" NL
6680 			   "} g_material[4];" NL "layout(binding = 4, std430) buffer OutputBuffer {" NL "  vec3 color[4];" NL
6681 			   "};" NL "uniform int g_material_id;" NL "void main() {" NL
6682 			   "  color[gl_LocalInvocationIndex] = vec3(g_material[g_material_id].color);" NL "}";
6683 
6684 		m_program = CreateProgramCS(glsl_cs);
6685 		glLinkProgram(m_program);
6686 		if (!CheckProgram(m_program))
6687 			return ERROR;
6688 
6689 		glGenBuffers(5, m_storage_buffer);
6690 
6691 		/* material buffers */
6692 		const float data[4][3] = {
6693 			{ 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }
6694 		};
6695 
6696 		for (GLuint i = 0; i < 4; ++i)
6697 		{
6698 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
6699 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data[i]), data[i], GL_DYNAMIC_DRAW);
6700 		}
6701 
6702 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
6703 		glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
6704 
6705 		glUseProgram(m_program);
6706 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 1);
6707 		glDispatchCompute(1, 1, 1);
6708 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
6709 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6710 		GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6711 		if (!out_data)
6712 			return ERROR;
6713 		const float* expected = &data[1][0];
6714 
6715 		for (int i = 0; i < 4; ++i)
6716 		{
6717 			if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6718 				out_data[i * 4 + 2] != expected[2])
6719 			{
6720 				m_context.getTestContext().getLog()
6721 					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6722 					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6723 					<< expected[2] << tcu::TestLog::EndMessage;
6724 				status = false;
6725 			}
6726 		}
6727 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6728 		glUniform1i(glGetUniformLocation(m_program, "g_material_id"), 3);
6729 		glDispatchCompute(1, 1, 1);
6730 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6731 		out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
6732 		if (!out_data)
6733 			return ERROR;
6734 		expected = &data[3][0];
6735 
6736 		for (int i = 0; i < 4; ++i)
6737 		{
6738 			if (out_data[i * 4 + 0] != expected[0] || out_data[i * 4 + 1] != expected[1] ||
6739 				out_data[i * 4 + 2] != expected[2])
6740 			{
6741 				m_context.getTestContext().getLog()
6742 					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 0] << ", " << out_data[i * 4 + 1]
6743 					<< ", " << out_data[i * 4 + 2] << ", but expected: " << expected[0] << ", " << expected[1] << ", "
6744 					<< expected[2] << tcu::TestLog::EndMessage;
6745 				status = false;
6746 			}
6747 		}
6748 
6749 		if (!status)
6750 		{
6751 			return ERROR;
6752 		}
6753 		return NO_ERROR;
6754 	}
6755 
Cleanup()6756 	virtual long Cleanup()
6757 	{
6758 		glUseProgram(0);
6759 		glDeleteProgram(m_program);
6760 		glDeleteBuffers(5, m_storage_buffer);
6761 		return NO_ERROR;
6762 	}
6763 };
6764 
6765 //-----------------------------------------------------------------------------
6766 // 2.5.1 AdvancedReadWriteCase1
6767 //-----------------------------------------------------------------------------
6768 class AdvancedReadWriteCase1 : public ShaderStorageBufferObjectBase
6769 {
6770 	GLuint m_program;
6771 	GLuint m_storage_buffer;
6772 	GLuint m_vertex_array;
6773 	GLuint m_vertex_buffer;
6774 
Setup()6775 	virtual long Setup()
6776 	{
6777 		m_program		 = 0;
6778 		m_storage_buffer = 0;
6779 		m_vertex_array   = 0;
6780 		m_vertex_buffer  = 0;
6781 		return NO_ERROR;
6782 	}
6783 
Run()6784 	virtual long Run()
6785 	{
6786 		if (!SupportedInVS(1))
6787 			return NOT_SUPPORTED;
6788 
6789 		const char* const glsl_vs = NL "layout(location = 0) in vec4 g_in_position;" NL "coherent buffer Buffer {" NL
6790 									   "  vec4 in_color;" NL "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL
6791 									   "  if (gl_VertexID == 0) {" NL "    g_buffer.out_color = g_buffer.in_color;" NL
6792 									   "    memoryBarrier();" NL "  }" NL "  gl_Position = g_in_position;" NL "}";
6793 
6794 		const char* const glsl_fs =
6795 			NL "layout(location = 0) out vec4 g_fs_out;" NL "coherent buffer Buffer {" NL "  vec4 in_color;" NL
6796 			   "  vec4 out_color;" NL "} g_buffer;" NL "void main() {" NL "  g_fs_out = g_buffer.out_color;" NL "}";
6797 
6798 		m_program = CreateProgram(glsl_vs, glsl_fs);
6799 		glLinkProgram(m_program);
6800 		if (!CheckProgram(m_program))
6801 			return ERROR;
6802 
6803 		glGenBuffers(1, &m_storage_buffer);
6804 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6805 		glBufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(float) * 4, NULL, GL_DYNAMIC_DRAW);
6806 		float* ptr = reinterpret_cast<float*>(glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY));
6807 		if (!ptr)
6808 			return ERROR;
6809 		*ptr++ = 0.0f;
6810 		*ptr++ = 1.0f;
6811 		*ptr++ = 0.0f;
6812 		*ptr++ = 1.0f;
6813 		*ptr++ = 0.0f;
6814 		*ptr++ = 0.0f;
6815 		*ptr++ = 0.0f;
6816 		*ptr++ = 0.0f;
6817 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6818 
6819 		/* vertex buffer */
6820 		{
6821 			const float data[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
6822 			glGenBuffers(1, &m_vertex_buffer);
6823 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6824 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
6825 			glBindBuffer(GL_ARRAY_BUFFER, 0);
6826 		}
6827 
6828 		glGenVertexArrays(1, &m_vertex_array);
6829 		glBindVertexArray(m_vertex_array);
6830 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
6831 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
6832 		glBindBuffer(GL_ARRAY_BUFFER, 0);
6833 		glEnableVertexAttribArray(0);
6834 		glBindVertexArray(0);
6835 
6836 		glClear(GL_COLOR_BUFFER_BIT);
6837 		glUseProgram(m_program);
6838 		glBindVertexArray(m_vertex_array);
6839 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6840 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(0, 1, 0)))
6841 		{
6842 			return ERROR;
6843 		}
6844 
6845 		// update input color
6846 		ptr = reinterpret_cast<float*>(
6847 			glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(float) * 4, GL_MAP_WRITE_BIT));
6848 		if (!ptr)
6849 			return ERROR;
6850 		*ptr++ = 1.0f;
6851 		*ptr++ = 0.0f;
6852 		*ptr++ = 1.0f;
6853 		*ptr++ = 1.0f;
6854 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6855 
6856 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6857 		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec3(1.0f, 0.0f, 1.0f)))
6858 		{
6859 			return ERROR;
6860 		}
6861 
6862 		return NO_ERROR;
6863 	}
6864 
Cleanup()6865 	virtual long Cleanup()
6866 	{
6867 		glUseProgram(0);
6868 		glDeleteProgram(m_program);
6869 		glDeleteBuffers(1, &m_storage_buffer);
6870 		glDeleteBuffers(1, &m_vertex_buffer);
6871 		glDeleteVertexArrays(1, &m_vertex_array);
6872 		return NO_ERROR;
6873 	}
6874 };
6875 
6876 class AdvancedReadWriteCase1CS : public ShaderStorageBufferObjectBase
6877 {
6878 	GLuint m_program;
6879 	GLuint m_storage_buffer;
6880 
Setup()6881 	virtual long Setup()
6882 	{
6883 		m_program		 = 0;
6884 		m_storage_buffer = 0;
6885 		return NO_ERROR;
6886 	}
6887 
Run()6888 	virtual long Run()
6889 	{
6890 		bool status = true;
6891 
6892 		const char* const glsl_cs = NL
6893 			"layout(local_size_x = 128) in;" NL "struct s {" NL "  int ene;" NL "  int due;" NL "  int like;" NL
6894 			"  int fake;" NL "};" NL "layout(std430) coherent buffer Buffer {" NL "  s a[128];" NL "} g_buffer;" NL
6895 			"void main() {" NL "  g_buffer.a[gl_LocalInvocationIndex].due = g_buffer.a[gl_LocalInvocationIndex].ene;" NL
6896 			"  groupMemoryBarrier();" NL "  barrier();" NL "  g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].like = "
6897 			"g_buffer.a[(gl_LocalInvocationIndex + 1u) % 128u].due;" NL "  groupMemoryBarrier();" NL "  barrier();" NL
6898 			"  g_buffer.a[(gl_LocalInvocationIndex + 17u) % 128u].fake "
6899 			"= g_buffer.a[(gl_LocalInvocationIndex + 17u) % "
6900 			"128u].like;" NL "}";
6901 		m_program = CreateProgramCS(glsl_cs);
6902 		glLinkProgram(m_program);
6903 		if (!CheckProgram(m_program))
6904 			return ERROR;
6905 
6906 		glGenBuffers(1, &m_storage_buffer);
6907 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
6908 		GLint data[128 * 4];
6909 		for (int i = 0; i < 128; ++i)
6910 		{
6911 			data[i * 4]		= i + 256;
6912 			data[i * 4 + 1] = 0;
6913 			data[i * 4 + 2] = 0;
6914 			data[i * 4 + 3] = 0;
6915 		}
6916 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6917 
6918 		glUseProgram(m_program);
6919 		glDispatchCompute(1, 1, 1);
6920 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6921 		GLint* out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6922 		if (!out_data)
6923 			return ERROR;
6924 		for (int i = 0; i < 128; ++i)
6925 		{
6926 			if (out_data[i * 4 + 3] != data[i * 4])
6927 			{
6928 				m_context.getTestContext().getLog()
6929 					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6930 					<< ", but expected: " << data[i * 4] << " -> " << out_data[i * 4 + 1] << " -> "
6931 					<< out_data[i * 4 + 2] << tcu::TestLog::EndMessage;
6932 				status = false;
6933 			}
6934 		}
6935 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
6936 		for (int i = 0; i < 128; ++i)
6937 		{
6938 			data[i * 4]		= i + 512;
6939 			data[i * 4 + 1] = 0;
6940 			data[i * 4 + 2] = 0;
6941 			data[i * 4 + 3] = 0;
6942 		}
6943 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
6944 
6945 		glDispatchCompute(1, 1, 1);
6946 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
6947 		out_data = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
6948 		if (!out_data)
6949 			return ERROR;
6950 		for (int i = 0; i < 128; ++i)
6951 		{
6952 			if (out_data[i * 4 + 3] != data[i * 4])
6953 			{
6954 				m_context.getTestContext().getLog()
6955 					<< tcu::TestLog::Message << "Received: " << out_data[i * 4 + 3] << ", "
6956 					<< ", but expected: " << data[i * 4] << tcu::TestLog::EndMessage;
6957 				status = false;
6958 			}
6959 		}
6960 		if (status)
6961 			return NO_ERROR;
6962 		else
6963 			return ERROR;
6964 	}
6965 
Cleanup()6966 	virtual long Cleanup()
6967 	{
6968 		glUseProgram(0);
6969 		glDeleteProgram(m_program);
6970 		glDeleteBuffers(1, &m_storage_buffer);
6971 		return NO_ERROR;
6972 	}
6973 };
6974 //-----------------------------------------------------------------------------
6975 // 2.6.1 AdvancedUsageCase1
6976 //-----------------------------------------------------------------------------
6977 
6978 class AdvancedUsageCase1 : public ShaderStorageBufferObjectBase
6979 {
6980 	GLuint m_program;
6981 	GLuint m_storage_buffer[3];
6982 	GLuint m_vertex_array;
6983 	GLuint m_vertex_buffer;
6984 	GLuint m_fbo, m_rt;
6985 
Setup()6986 	virtual long Setup()
6987 	{
6988 		m_program = 0;
6989 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
6990 		m_vertex_array  = 0;
6991 		m_vertex_buffer = 0;
6992 		glGenFramebuffers(1, &m_fbo);
6993 		glGenTextures(1, &m_rt);
6994 		return NO_ERROR;
6995 	}
6996 
Run()6997 	virtual long Run()
6998 	{
6999 		if (!SupportedInVS(1))
7000 			return NOT_SUPPORTED;
7001 
7002 		const char* const glsl_vs =
7003 			NL "layout(location = 0) in vec4 g_position;" NL "layout(location = 1) in int g_object_id;" NL
7004 			   "out StageData {" NL "  flat int object_id;" NL "} g_vs_out;" NL
7005 			   "layout(binding = 0, std430) buffer TransformBuffer {" NL "  mat4 g_transform[];" NL "};" NL
7006 			   "void main() {" NL "  mat4 mvp = g_transform[g_object_id];" NL "  gl_Position = mvp * g_position;" NL
7007 			   "  g_vs_out.object_id = g_object_id;" NL "}";
7008 
7009 		const char* const glsl_fs = NL
7010 			"in StageData {" NL "  flat int object_id;" NL "} g_fs_in;" NL "layout(location = 0) out vec4 g_fs_out;" NL
7011 			"struct Material {" NL "  vec3 color;" NL "};" NL "layout(binding = 1, std430) buffer MaterialBuffer {" NL
7012 			"  Material g_material[4];" NL "};" NL "layout(binding = 2, std430) buffer MaterialIDBuffer {" NL
7013 			"  int g_material_id[4];" NL "};" NL "void main() {" NL "  int mid = g_material_id[g_fs_in.object_id];" NL
7014 			"  Material m = g_material[mid];" NL "  g_fs_out = vec4(m.color, 1);" NL "}";
7015 
7016 		m_program = CreateProgram(glsl_vs, glsl_fs);
7017 		glLinkProgram(m_program);
7018 		if (!CheckProgram(m_program))
7019 			return ERROR;
7020 
7021 		glGenBuffers(3, m_storage_buffer);
7022 
7023 		/* transform buffer */
7024 		{
7025 			mat4 data[] = { Translation(-0.5f, -0.5f, 0.0f), Translation(0.5f, -0.5f, 0.0f),
7026 							Translation(-0.5f, 0.5f, 0.0f), Translation(0.5f, 0.5f, 0.0f) };
7027 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7028 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7029 		}
7030 		/* material buffer */
7031 		{
7032 			vec4 data[] = { vec4(1, 0, 0, 1), vec4(0, 1, 0, 1), vec4(0, 0, 1, 0), vec4(1, 1, 0, 1) };
7033 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7034 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7035 		}
7036 		/* material id buffer */
7037 		{
7038 			int data[] = { 0, 1, 2, 3 };
7039 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7040 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7041 		}
7042 		/* vertex buffer */
7043 		{
7044 			struct
7045 			{
7046 				vec2 position;
7047 				int  object_id;
7048 			} data[] = { { vec2(-0.4f, -0.4f), 0 }, { vec2(0.4f, -0.4f), 0 },  { vec2(-0.4f, 0.4f), 0 },
7049 						 { vec2(0.4f, 0.4f), 0 },   { vec2(-0.4f, -0.4f), 1 }, { vec2(0.4f, -0.4f), 1 },
7050 						 { vec2(-0.4f, 0.4f), 1 },  { vec2(0.4f, 0.4f), 1 },   { vec2(-0.4f, -0.4f), 2 },
7051 						 { vec2(0.4f, -0.4f), 2 },  { vec2(-0.4f, 0.4f), 2 },  { vec2(0.4f, 0.4f), 2 },
7052 						 { vec2(-0.4f, -0.4f), 3 }, { vec2(0.4f, -0.4f), 3 },  { vec2(-0.4f, 0.4f), 3 },
7053 						 { vec2(0.4f, 0.4f), 3 } };
7054 			glGenBuffers(1, &m_vertex_buffer);
7055 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7056 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
7057 			glBindBuffer(GL_ARRAY_BUFFER, 0);
7058 		}
7059 
7060 		glBindTexture(GL_TEXTURE_2D, m_rt);
7061 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7062 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
7063 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
7064 		glBindTexture(GL_TEXTURE_2D, 0);
7065 		glViewport(0, 0, 100, 100);
7066 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
7067 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
7068 
7069 		glGenVertexArrays(1, &m_vertex_array);
7070 		glBindVertexArray(m_vertex_array);
7071 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
7072 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(vec2) + sizeof(int), 0);
7073 		glVertexAttribIPointer(1, 1, GL_INT, sizeof(vec2) + sizeof(int), reinterpret_cast<void*>(sizeof(vec2)));
7074 		glBindBuffer(GL_ARRAY_BUFFER, 0);
7075 		glEnableVertexAttribArray(0);
7076 		glEnableVertexAttribArray(1);
7077 		glBindVertexArray(0);
7078 
7079 		glClear(GL_COLOR_BUFFER_BIT);
7080 		glUseProgram(m_program);
7081 		glBindVertexArray(m_vertex_array);
7082 		/* draw */
7083 		{
7084 			const GLint   first[4] = { 0, 4, 8, 12 };
7085 			const GLsizei count[4] = { 4, 4, 4, 4 };
7086 			glMultiDrawArrays(GL_TRIANGLE_STRIP, first, count, 4);
7087 		}
7088 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(1, 1, 0), vec3(0, 0, 1)))
7089 		{
7090 			return ERROR;
7091 		}
7092 		return NO_ERROR;
7093 	}
7094 
Cleanup()7095 	virtual long Cleanup()
7096 	{
7097 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
7098 		glUseProgram(0);
7099 		glDeleteProgram(m_program);
7100 		glDeleteBuffers(3, m_storage_buffer);
7101 		glDeleteBuffers(1, &m_vertex_buffer);
7102 		glDeleteVertexArrays(1, &m_vertex_array);
7103 		glDeleteFramebuffers(1, &m_fbo);
7104 		glDeleteTextures(1, &m_rt);
7105 		return NO_ERROR;
7106 	}
7107 };
7108 //-----------------------------------------------------------------------------
7109 // 2.6.2 AdvancedUsageSync
7110 //-----------------------------------------------------------------------------
7111 
7112 class AdvancedUsageSync : public ShaderStorageBufferObjectBase
7113 {
7114 	GLuint m_program;
7115 	GLuint m_storage_buffer[7];
7116 	GLuint m_vertex_array;
7117 
Setup()7118 	virtual long Setup()
7119 	{
7120 		m_program = 0;
7121 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7122 		m_vertex_array = 0;
7123 		return NO_ERROR;
7124 	}
7125 
Run()7126 	virtual long Run()
7127 	{
7128 		if (!SupportedInVS(3))
7129 			return NOT_SUPPORTED;
7130 
7131 		const char* const glsl_vs =
7132 			NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL "  int g_data0, g_inc0;" NL
7133 			   "  int g_data1, g_inc1;" NL "};" NL "layout(std430, binding = 1) buffer Buffer12 {" NL
7134 			   "  int inc, data;" NL "} g_buffer12[2];" NL NL "void Modify(int path) {" NL "  if (path == 0) {" NL
7135 			   "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
7136 			   "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
7137 			   "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
7138 			   "  }" NL NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
7139 			   "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
7140 			   "void main() {" NL "  Modify(gl_VertexID);" NL "  gl_Position = vec4(0, 0, 0, 1);" NL "}";
7141 
7142 		const char* glsl_fs =
7143 			NL "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
7144 			   "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
7145 			   "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7146 			   "  int inc, data;" NL "} g_buffer56[2];" NL NL "void ModifyFS(int path) {" NL "  if (path == 0) {" NL
7147 			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7148 			   "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7149 			   "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
7150 			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7151 			   "  }" NL NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
7152 			   "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL
7153 			   "void main() {" NL "  atomicAdd(g_buffer3.data, 1);" NL "  ModifyFS(gl_PrimitiveID);" NL "}";
7154 
7155 		m_program = CreateProgram(glsl_vs, glsl_fs);
7156 		glLinkProgram(m_program);
7157 		if (!CheckProgram(m_program))
7158 			return ERROR;
7159 
7160 		glGenVertexArrays(1, &m_vertex_array);
7161 		glGenBuffers(7, m_storage_buffer);
7162 
7163 		/* Buffer0 */
7164 		{
7165 			int data[4] = { 0, 1, 0, 2 };
7166 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7167 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7168 		}
7169 		/* Buffer1 */
7170 		{
7171 			int data[2] = { 3, 1 };
7172 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7173 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7174 		}
7175 		/* Buffer2 */
7176 		{
7177 			int data[2] = { 2, 4 };
7178 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7179 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7180 		}
7181 		/* Buffer3 */
7182 		{
7183 			int data[1] = { 0 };
7184 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7185 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7186 		}
7187 		/* Buffer4 */
7188 		{
7189 			int data[4] = { 0, 1, 0, 2 };
7190 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7191 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7192 		}
7193 		/* Buffer5 */
7194 		{
7195 			int data[2] = { 3, 1 };
7196 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7197 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7198 		}
7199 		/* Buffer6 */
7200 		{
7201 			int data[2] = { 2, 4 };
7202 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7203 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7204 		}
7205 
7206 		glUseProgram(m_program);
7207 		glBindVertexArray(m_vertex_array);
7208 
7209 		glDrawArrays(GL_POINTS, 0, 3);
7210 		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7211 		glDrawArrays(GL_POINTS, 0, 3);
7212 
7213 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7214 
7215 		/* Buffer0 */
7216 		{
7217 			const int ref_data[4] = { 4, 1, 4, 2 };
7218 			int		  data[4];
7219 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7220 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7221 			for (int i = 0; i < 4; ++i)
7222 			{
7223 				if (data[i] != ref_data[i])
7224 				{
7225 					m_context.getTestContext().getLog()
7226 						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7227 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7228 					return ERROR;
7229 				}
7230 			}
7231 		}
7232 		/* Buffer1 */
7233 		{
7234 			const int ref_data[2] = { 3, 5 };
7235 			int		  data[2];
7236 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7237 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7238 			for (int i = 0; i < 2; ++i)
7239 			{
7240 				if (data[i] != ref_data[i])
7241 				{
7242 					m_context.getTestContext().getLog()
7243 						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7244 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7245 					return ERROR;
7246 				}
7247 			}
7248 		}
7249 		/* Buffer2 */
7250 		{
7251 			const int ref_data[2] = { 2, 10 };
7252 			int		  data[2];
7253 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7254 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7255 			for (int i = 0; i < 2; ++i)
7256 			{
7257 				if (data[i] != ref_data[i])
7258 				{
7259 					m_context.getTestContext().getLog()
7260 						<< tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7261 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7262 					return ERROR;
7263 				}
7264 			}
7265 		}
7266 		/* Buffer3 */
7267 		{
7268 			const int ref_data[1] = { 6 };
7269 			int		  data[1];
7270 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7271 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7272 			for (int i = 0; i < 1; ++i)
7273 			{
7274 				if (data[i] != ref_data[i])
7275 				{
7276 					m_context.getTestContext().getLog()
7277 						<< tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7278 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7279 					return ERROR;
7280 				}
7281 			}
7282 		}
7283 		/* Buffer4 */
7284 		{
7285 			const int ref_data[4] = { 4, 1, 4, 2 };
7286 			int		  data[4];
7287 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7288 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7289 			for (int i = 0; i < 4; ++i)
7290 			{
7291 				if (data[i] != ref_data[i])
7292 				{
7293 					m_context.getTestContext().getLog()
7294 						<< tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7295 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7296 					return ERROR;
7297 				}
7298 			}
7299 		}
7300 		/* Buffer5 */
7301 		{
7302 			const int ref_data[2] = { 3, 5 };
7303 			int		  data[2];
7304 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7305 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7306 			for (int i = 0; i < 2; ++i)
7307 			{
7308 				if (data[i] != ref_data[i])
7309 				{
7310 					m_context.getTestContext().getLog()
7311 						<< tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7312 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7313 					return ERROR;
7314 				}
7315 			}
7316 		}
7317 		/* Buffer6 */
7318 		{
7319 			const int ref_data[2] = { 2, 10 };
7320 			int		  data[2];
7321 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7322 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7323 			for (int i = 0; i < 2; ++i)
7324 			{
7325 				if (data[i] != ref_data[i])
7326 				{
7327 					m_context.getTestContext().getLog()
7328 						<< tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7329 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7330 					return ERROR;
7331 				}
7332 			}
7333 		}
7334 
7335 		return NO_ERROR;
7336 	}
7337 
Cleanup()7338 	virtual long Cleanup()
7339 	{
7340 		glUseProgram(0);
7341 		glDeleteProgram(m_program);
7342 		glDeleteBuffers(7, m_storage_buffer);
7343 		glDeleteVertexArrays(1, &m_vertex_array);
7344 		return NO_ERROR;
7345 	}
7346 };
7347 
7348 class AdvancedUsageSyncCS : public ShaderStorageBufferObjectBase
7349 {
7350 	GLuint m_program;
7351 	GLuint m_storage_buffer[7];
7352 
Setup()7353 	virtual long Setup()
7354 	{
7355 		m_program = 0;
7356 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7357 		return NO_ERROR;
7358 	}
7359 
Run()7360 	virtual long Run()
7361 	{
7362 		const char* const glsl_cs =
7363 			NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) coherent buffer Buffer0 {" NL
7364 			   "  int g_data0, g_inc0;" NL "  int g_data1, g_inc1;" NL "};" NL
7365 			   "layout(std430, binding = 1) buffer Buffer12 {" NL "  int inc, data;" NL "} g_buffer12[2];" NL
7366 			   "layout(binding = 3, std430) coherent buffer Buffer3 {" NL "  int data;" NL "} g_buffer3;" NL
7367 			   "layout(std430, binding = 4) coherent buffer Buffer4 {" NL "  int data0, inc0;" NL
7368 			   "  int data1, inc1;" NL "} g_buffer4;" NL "layout(std430, binding = 5) buffer Buffer56 {" NL
7369 			   "  int inc, data;" NL "} g_buffer56[2];" NL NL "void Modify1(int path) {" NL "  if (path == 0) {" NL
7370 			   "    atomicAdd(g_data0, g_inc0);" NL "    atomicAdd(g_data1, g_inc0);" NL "  } else if (path == 1) {" NL
7371 			   "    atomicAdd(g_data0, - g_inc0);" NL "    atomicAdd(g_data1, - g_inc0);" NL
7372 			   "  } else if (path == 2) {" NL "    atomicAdd(g_data0, g_inc1);" NL "    atomicAdd(g_data1, g_inc1);" NL
7373 			   "  }" NL "  if (path == 0) {" NL "    g_buffer12[0].data += g_buffer12[1].inc;" NL
7374 			   "  } else if (path == 1) {" NL "    g_buffer12[1].data += g_buffer12[0].inc;" NL "  }" NL "}" NL NL
7375 			   "void Modify2(int path) {" NL "  if (path == 0) {" NL
7376 			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc0);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc0);" NL
7377 			   "  } else if (path == 1) {" NL "    atomicAdd(g_buffer4.data0, - g_buffer4.inc0);" NL
7378 			   "    atomicAdd(g_buffer4.data1, - g_buffer4.inc0);" NL "  } else if (path == 2) {" NL
7379 			   "    atomicAdd(g_buffer4.data0, g_buffer4.inc1);" NL "    atomicAdd(g_buffer4.data1, g_buffer4.inc1);" NL
7380 			   "  }" NL "  if (path == 0) {" NL "    g_buffer56[0].data += g_buffer56[1].inc;" NL
7381 			   "  } else if (path == 1) {" NL "    g_buffer56[1].data += g_buffer56[0].inc;" NL "  }" NL "}" NL NL
7382 			   "void main() {" NL "  Modify1(int(gl_WorkGroupID.z));" NL "  atomicAdd(g_buffer3.data, 1);" NL
7383 			   "  Modify2(int(gl_WorkGroupID.z));" NL "}";
7384 
7385 		m_program = CreateProgramCS(glsl_cs);
7386 		glLinkProgram(m_program);
7387 		if (!CheckProgram(m_program))
7388 			return ERROR;
7389 
7390 		glGenBuffers(7, m_storage_buffer);
7391 
7392 		/* Buffer0 */
7393 		{
7394 			int data[4] = { 0, 1, 0, 2 };
7395 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7396 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7397 		}
7398 		/* Buffer1 */
7399 		{
7400 			int data[2] = { 3, 1 };
7401 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7402 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7403 		}
7404 		/* Buffer2 */
7405 		{
7406 			int data[2] = { 2, 4 };
7407 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7408 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7409 		}
7410 		/* Buffer3 */
7411 		{
7412 			int data[1] = { 0 };
7413 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7414 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7415 		}
7416 		/* Buffer4 */
7417 		{
7418 			int data[4] = { 0, 1, 0, 2 };
7419 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7420 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7421 		}
7422 		/* Buffer5 */
7423 		{
7424 			int data[2] = { 3, 1 };
7425 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m_storage_buffer[5]);
7426 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7427 		}
7428 		/* Buffer6 */
7429 		{
7430 			int data[2] = { 2, 4 };
7431 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 6, m_storage_buffer[6]);
7432 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7433 		}
7434 
7435 		glUseProgram(m_program);
7436 
7437 		glDispatchCompute(1, 1, 3);
7438 		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
7439 		glDispatchCompute(1, 1, 3);
7440 
7441 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7442 
7443 		/* Buffer0 */
7444 		{
7445 			const int ref_data[4] = { 4, 1, 4, 2 };
7446 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7447 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7448 			if (!data)
7449 				return ERROR;
7450 			for (int i = 0; i < 4; ++i)
7451 			{
7452 				if (data[i] != ref_data[i])
7453 				{
7454 					m_context.getTestContext().getLog()
7455 						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7456 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7457 					return ERROR;
7458 				}
7459 			}
7460 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7461 		}
7462 		/* Buffer1 */
7463 		{
7464 			const int ref_data[2] = { 3, 5 };
7465 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7466 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7467 			if (!data)
7468 				return ERROR;
7469 			for (int i = 0; i < 2; ++i)
7470 			{
7471 				if (data[i] != ref_data[i])
7472 				{
7473 					m_context.getTestContext().getLog()
7474 						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7475 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7476 					return ERROR;
7477 				}
7478 			}
7479 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7480 		}
7481 		/* Buffer2 */
7482 		{
7483 			const int ref_data[2] = { 2, 10 };
7484 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[2]);
7485 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7486 			if (!data)
7487 				return ERROR;
7488 			for (int i = 0; i < 2; ++i)
7489 			{
7490 				if (data[i] != ref_data[i])
7491 				{
7492 					m_context.getTestContext().getLog()
7493 						<< tcu::TestLog::Message << "[Buffer2] Data at index " << i << " is " << data[i]
7494 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7495 					return ERROR;
7496 				}
7497 			}
7498 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7499 		}
7500 		/* Buffer3 */
7501 		{
7502 			const int ref_data[1] = { 6 };
7503 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[3]);
7504 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
7505 			if (!data)
7506 				return ERROR;
7507 			for (int i = 0; i < 1; ++i)
7508 			{
7509 				if (data[i] != ref_data[i])
7510 				{
7511 					m_context.getTestContext().getLog()
7512 						<< tcu::TestLog::Message << "[Buffer3] Data at index " << i << " is " << data[i]
7513 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7514 					return ERROR;
7515 				}
7516 			}
7517 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7518 		}
7519 		/* Buffer4 */
7520 		{
7521 			const int ref_data[4] = { 4, 1, 4, 2 };
7522 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7523 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7524 			if (!data)
7525 				return ERROR;
7526 			for (int i = 0; i < 4; ++i)
7527 			{
7528 				if (data[i] != ref_data[i])
7529 				{
7530 					m_context.getTestContext().getLog()
7531 						<< tcu::TestLog::Message << "[Buffer4] Data at index " << i << " is " << data[i]
7532 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7533 					return ERROR;
7534 				}
7535 			}
7536 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7537 		}
7538 		/* Buffer5 */
7539 		{
7540 			const int ref_data[2] = { 3, 5 };
7541 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[5]);
7542 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7543 			if (!data)
7544 				return ERROR;
7545 			for (int i = 0; i < 2; ++i)
7546 			{
7547 				if (data[i] != ref_data[i])
7548 				{
7549 					m_context.getTestContext().getLog()
7550 						<< tcu::TestLog::Message << "[Buffer5] Data at index " << i << " is " << data[i]
7551 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7552 					return ERROR;
7553 				}
7554 			}
7555 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7556 		}
7557 		/* Buffer6 */
7558 		{
7559 			const int ref_data[2] = { 2, 10 };
7560 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
7561 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 8, GL_MAP_READ_BIT);
7562 			if (!data)
7563 				return ERROR;
7564 			for (int i = 0; i < 2; ++i)
7565 			{
7566 				if (data[i] != ref_data[i])
7567 				{
7568 					m_context.getTestContext().getLog()
7569 						<< tcu::TestLog::Message << "[Buffer6] Data at index " << i << " is " << data[i]
7570 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7571 					return ERROR;
7572 				}
7573 			}
7574 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7575 		}
7576 
7577 		return NO_ERROR;
7578 	}
7579 
Cleanup()7580 	virtual long Cleanup()
7581 	{
7582 		glUseProgram(0);
7583 		glDeleteProgram(m_program);
7584 		glDeleteBuffers(7, m_storage_buffer);
7585 		return NO_ERROR;
7586 	}
7587 };
7588 
7589 //-----------------------------------------------------------------------------
7590 // 2.6.3 AdvancedUsageOperators
7591 //-----------------------------------------------------------------------------
7592 class AdvancedUsageOperators : public ShaderStorageBufferObjectBase
7593 {
7594 	GLuint m_program;
7595 	GLuint m_storage_buffer[2];
7596 	GLuint m_vertex_array;
7597 
Setup()7598 	virtual long Setup()
7599 	{
7600 		m_program = 0;
7601 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7602 		m_vertex_array = 0;
7603 		return NO_ERROR;
7604 	}
7605 
Run()7606 	virtual long Run()
7607 	{
7608 		if (!SupportedInVS(2))
7609 			return NOT_SUPPORTED;
7610 
7611 		const char* const glsl_vs =
7612 			NL "layout(std430, binding = 0) buffer Buffer0 {" NL "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL
7613 			   "layout(std430, binding = 1) buffer Buffer1 {" NL "  int i0;" NL "} g_buffer1;" NL
7614 			   "uniform int g_values[] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL "  g_o0 += g_i0;" NL
7615 			   "  g_o0 <<= 1;" NL "  g_o0 = g_i0 > g_o0 ? g_i0 : g_o0;" NL "  g_o0 *= g_i0;" NL
7616 			   "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7617 			   "  g_o0 &= g_buffer1.i0;" NL "}";
7618 
7619 		m_program = CreateProgram(glsl_vs, "");
7620 		glLinkProgram(m_program);
7621 		if (!CheckProgram(m_program))
7622 			return ERROR;
7623 
7624 		glGenVertexArrays(1, &m_vertex_array);
7625 		glGenBuffers(2, m_storage_buffer);
7626 
7627 		/* Buffer0 */
7628 		{
7629 			int data[4] = { 3, 5 };
7630 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7631 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7632 		}
7633 		/* Buffer1 */
7634 		{
7635 			int data[1] = { 0 };
7636 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7637 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7638 		}
7639 
7640 		glEnable(GL_RASTERIZER_DISCARD);
7641 		glUseProgram(m_program);
7642 		glBindVertexArray(m_vertex_array);
7643 		glDrawArrays(GL_POINTS, 0, 1);
7644 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7645 
7646 		/* Buffer0 */
7647 		{
7648 			const int ref_data[2] = { 3, 37 };
7649 			int		  data[4];
7650 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7651 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7652 			for (int i = 0; i < 2; ++i)
7653 			{
7654 				if (data[i] != ref_data[i])
7655 				{
7656 					m_context.getTestContext().getLog()
7657 						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7658 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7659 					return ERROR;
7660 				}
7661 			}
7662 		}
7663 		/* Buffer0 */
7664 		{
7665 			const int ref_data[1] = { 0xff2f };
7666 			int		  data[1];
7667 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[1]);
7668 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7669 			for (int i = 0; i < 1; ++i)
7670 			{
7671 				if (data[i] != ref_data[i])
7672 				{
7673 					m_context.getTestContext().getLog()
7674 						<< tcu::TestLog::Message << "[Buffer1] Data at index " << i << " is " << data[i]
7675 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7676 					return ERROR;
7677 				}
7678 			}
7679 		}
7680 
7681 		return NO_ERROR;
7682 	}
7683 
Cleanup()7684 	virtual long Cleanup()
7685 	{
7686 		glDisable(GL_RASTERIZER_DISCARD);
7687 		glUseProgram(0);
7688 		glDeleteProgram(m_program);
7689 		glDeleteBuffers(2, m_storage_buffer);
7690 		glDeleteVertexArrays(1, &m_vertex_array);
7691 		return NO_ERROR;
7692 	}
7693 };
7694 
7695 class AdvancedUsageOperatorsCS : public ShaderStorageBufferObjectBase
7696 {
7697 	GLuint m_program;
7698 	GLuint m_storage_buffer[2];
7699 
Setup()7700 	virtual long Setup()
7701 	{
7702 		m_program = 0;
7703 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7704 		return NO_ERROR;
7705 	}
7706 
Run()7707 	virtual long Run()
7708 	{
7709 		const char* const glsl_cs =
7710 			NL "layout(local_size_x = 1) in;" NL "layout(std430, binding = 0) buffer Buffer0 {" NL
7711 			   "  readonly int g_i0;" NL "  int g_o0;" NL "};" NL "layout(std430, binding = 1) buffer Buffer1 {" NL
7712 			   "  int i0;" NL "} g_buffer1;" NL "const int g_values[6] = int[](1, 2, 3, 4, 5, 6);" NL "void main() {" NL
7713 			   "  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
7714 			   "  g_o0 = --g_o0 + g_values[g_i0];" NL "  g_o0++;" NL "  ++g_o0;" NL "  g_buffer1.i0 = 0xff2f;" NL
7715 			   "  g_o0 &= g_buffer1.i0;" NL "}";
7716 
7717 		m_program = CreateProgramCS(glsl_cs);
7718 		glLinkProgram(m_program);
7719 		if (!CheckProgram(m_program))
7720 			return ERROR;
7721 
7722 		glGenBuffers(2, m_storage_buffer);
7723 
7724 		/* Buffer0 */
7725 		{
7726 			int data[4] = { 3, 5 };
7727 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7728 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7729 		}
7730 		/* Buffer1 */
7731 		{
7732 			int data[1] = { 0 };
7733 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7734 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7735 		}
7736 
7737 		glUseProgram(m_program);
7738 		glDispatchCompute(1, 1, 1);
7739 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7740 
7741 		/* Buffer0 */
7742 		{
7743 			const int ref_data[2] = { 3, 37 };
7744 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[0]);
7745 			int* data = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 16, GL_MAP_READ_BIT);
7746 			if (!data)
7747 				return ERROR;
7748 			for (int i = 0; i < 2; ++i)
7749 			{
7750 				if (data[i] != ref_data[i])
7751 				{
7752 					m_context.getTestContext().getLog()
7753 						<< tcu::TestLog::Message << "[Buffer0] Data at index " << i << " is " << data[i]
7754 						<< " should be " << ref_data[i] << tcu::TestLog::EndMessage;
7755 					return ERROR;
7756 				}
7757 			}
7758 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
7759 		}
7760 
7761 		return NO_ERROR;
7762 	}
7763 
Cleanup()7764 	virtual long Cleanup()
7765 	{
7766 		glUseProgram(0);
7767 		glDeleteProgram(m_program);
7768 		glDeleteBuffers(2, m_storage_buffer);
7769 		return NO_ERROR;
7770 	}
7771 };
7772 
7773 //-----------------------------------------------------------------------------
7774 // 2.7 AdvancedUnsizedArrayLength
7775 //-----------------------------------------------------------------------------
7776 class AdvancedUnsizedArrayLength : public ShaderStorageBufferObjectBase
7777 {
7778 	GLuint m_program;
7779 	GLuint m_storage_buffer[5];
7780 	GLuint m_vertex_array;
7781 
Setup()7782 	virtual long Setup()
7783 	{
7784 		m_program = 0;
7785 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7786 		m_vertex_array = 0;
7787 		return NO_ERROR;
7788 	}
7789 
Run()7790 	virtual long Run()
7791 	{
7792 		if (!SupportedInVS(5))
7793 			return NOT_SUPPORTED;
7794 
7795 		const char* const glsl_vs =
7796 			NL "layout(std430, binding = 0) readonly buffer Input0 {" NL "  int g_input0[];" NL "};" NL
7797 			   "layout(std430, binding = 1) readonly buffer Input1 {" NL "  int data[];" NL "} g_input1;" NL
7798 			   "layout(std430, binding = 2) readonly buffer Input23 {" NL "  int data[];" NL "} g_input23[2];" NL
7799 			   "layout(std430, binding = 4) buffer Output {" NL "  int g_length[4];" NL "  int g_length2;" NL "};" NL
7800 			   "void main() {" NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7801 			   "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7802 			   "  g_length2 = g_length.length();" NL "}";
7803 
7804 		m_program = CreateProgram(glsl_vs, "");
7805 		glLinkProgram(m_program);
7806 		if (!CheckProgram(m_program))
7807 			return ERROR;
7808 
7809 		glGenVertexArrays(1, &m_vertex_array);
7810 		glGenBuffers(5, m_storage_buffer);
7811 
7812 		/* input 0 */
7813 		{
7814 			int data[7] = { 1, 2, 3, 4, 5, 6, 7 };
7815 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
7816 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7817 		}
7818 		/* input 1 */
7819 		{
7820 			int data[5] = { 1, 2, 3, 4, 5 };
7821 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
7822 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7823 		}
7824 		/* input 2 */
7825 		{
7826 			int data[3] = { 1, 2, 3 };
7827 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_storage_buffer[2]);
7828 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7829 		}
7830 		/* input 3 */
7831 		{
7832 			int data[4] = { 1, 2, 3, 4 };
7833 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_storage_buffer[3]);
7834 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7835 		}
7836 		/* output */
7837 		{
7838 			int data[5] = { 0 };
7839 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_storage_buffer[4]);
7840 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
7841 		}
7842 
7843 		glEnable(GL_RASTERIZER_DISCARD);
7844 		glUseProgram(m_program);
7845 		glBindVertexArray(m_vertex_array);
7846 		glDrawArrays(GL_POINTS, 0, 1);
7847 
7848 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
7849 
7850 		/* output */
7851 		{
7852 			int data[5];
7853 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
7854 			glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), data);
7855 			bool status = true;
7856 			if (data[0] != 7)
7857 			{
7858 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 0 length is " << data[0]
7859 													<< " should be 7." << tcu::TestLog::EndMessage;
7860 				status = false;
7861 			}
7862 			if (data[1] != 5)
7863 			{
7864 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 1 length is " << data[1]
7865 													<< " should be 5." << tcu::TestLog::EndMessage;
7866 				status = false;
7867 			}
7868 			if (data[2] != 3)
7869 			{
7870 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 2 length is " << data[2]
7871 													<< " should be 3." << tcu::TestLog::EndMessage;
7872 				status = false;
7873 			}
7874 			if (data[3] != 4)
7875 			{
7876 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 3 length is " << data[3]
7877 													<< " should be 4." << tcu::TestLog::EndMessage;
7878 				status = false;
7879 			}
7880 			if (data[4] != 4)
7881 			{
7882 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 length is " << data[4]
7883 													<< " should be 4." << tcu::TestLog::EndMessage;
7884 				status = false;
7885 			}
7886 			if (!status)
7887 				return ERROR;
7888 		}
7889 
7890 		return NO_ERROR;
7891 	}
7892 
Cleanup()7893 	virtual long Cleanup()
7894 	{
7895 		glDisable(GL_RASTERIZER_DISCARD);
7896 		glUseProgram(0);
7897 		glDeleteProgram(m_program);
7898 		glDeleteBuffers(5, m_storage_buffer);
7899 		glDeleteVertexArrays(1, &m_vertex_array);
7900 		return NO_ERROR;
7901 	}
7902 };
7903 
7904 class AdvancedUnsizedArrayLength2 : public ShaderStorageBufferObjectBase
7905 {
7906 	GLuint m_program;
7907 	GLuint m_storage_buffer[8];
7908 	GLuint m_vertex_array;
7909 
7910 	virtual void SetPath() = 0;
7911 
Setup()7912 	virtual long Setup()
7913 	{
7914 		m_program = 0;
7915 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
7916 		m_vertex_array = 0;
7917 		return NO_ERROR;
7918 	}
7919 
Cleanup()7920 	virtual long Cleanup()
7921 	{
7922 		glUseProgram(0);
7923 		glDeleteProgram(m_program);
7924 		glDeleteBuffers(8, m_storage_buffer);
7925 		if (stage != compute)
7926 			glDeleteVertexArrays(1, &m_vertex_array);
7927 		return NO_ERROR;
7928 	}
7929 
BuildShaderPT(int stagept)7930 	std::string BuildShaderPT(int stagept)
7931 	{
7932 		std::ostringstream os;
7933 		if (stagept == vertex)
7934 		{
7935 			os << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);";
7936 		}
7937 		if (stagept == fragment)
7938 		{
7939 			os << NL "void main() {";
7940 		}
7941 		os << NL "}";
7942 		return os.str();
7943 	}
7944 
BuildShader()7945 	std::string BuildShader()
7946 	{
7947 		std::ostringstream os;
7948 		std::string		   e[4][7] = { { "bvec3", "vec4", "ivec3", "ivec3", "uvec2", "vec2", "uvec4" },
7949 								{ "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7950 								{ "mat2", "mat3", "mat4", "mat4", "mat2x3", "mat3x2", "mat4x2" },
7951 								{ "S0", "S1", "S2", "S2", "S4", "S5", "S6" } };
7952 
7953 		std::string sd =
7954 			NL "struct S0 {" NL "  float f;" NL "  int i;" NL "  uint ui;" NL "  bool b;" NL "};" NL "struct S1 {" NL
7955 			   "  ivec3 iv;" NL "  bvec2 bv;" NL "  vec4 v;" NL "  uvec2 uv;" NL "};" NL "struct S2 {" NL
7956 			   "  mat2x2 m22;" NL "  mat4x4 m44;" NL "  mat2x3 m23;" NL "  mat4x2 m42;" NL "  mat3x4 m34;" NL "};" NL
7957 			   "struct S4 {" NL "  float f[1];" NL "  int i[2];" NL "  uint ui[3];" NL "  bool b[4];" NL
7958 			   "  ivec3 iv[5];" NL "  bvec2 bv[6];" NL "  vec4  v[7];" NL "  uvec2 uv[8];" NL "};" NL "struct S5 {" NL
7959 			   "  S0 s0;" NL "  S1 s1;" NL "  S2 s2;" NL "};" NL "struct S6 {" NL "  S4 s4[3];" NL "};";
7960 
7961 		std::string lo   = "";
7962 		std::string l[4] = { "std140", "std430", "shared", "packed" };
7963 		lo += l[layout];
7964 
7965 		if (etype == matrix_rm)
7966 			lo += ", row_major";
7967 
7968 		std::string decl = sd + NL "layout(" + lo + ") buffer;" NL "layout(binding = 0) readonly buffer Input0 {" +
7969 						   ((other_members) ? ("\n  " + e[etype][0] + " pad0;") : "") + NL "  " + e[etype][0] +
7970 						   " g_input0[];" NL "};" NL "layout(binding = 1) readonly buffer Input1 {" +
7971 						   ((other_members) ? ("\n  " + e[etype][1] + " pad1;") : "") + NL "  " + e[etype][1] +
7972 						   " data[];" NL "} g_input1;" NL "layout(binding = 2) readonly buffer Input23 {" +
7973 						   ((other_members) ? ("\n  " + e[etype][2] + " pad2;") : "") + NL "  " + e[etype][2] +
7974 						   " data[];" NL "} g_input23[2];" NL "layout(binding = 4) buffer Output0 {" +
7975 						   ((other_members) ? ("\n  " + e[etype][4] + " pad4;") : "") + NL "  " + e[etype][4] +
7976 						   " data[];" NL "} g_output0;" NL "layout(binding = 5) readonly buffer Input4 {" +
7977 						   ((other_members) ? ("\n  " + e[etype][5] + " pad5;") : "") + NL "  " + e[etype][5] +
7978 						   " data[];" NL "} g_input4;" NL "layout(binding = 6) buffer Output1 {" +
7979 						   ((other_members) ? ("\n  " + e[etype][6] + " pad6;") : "") + NL "  " + e[etype][6] +
7980 						   " data[];" NL "} g_output1;" NL "layout(std430, binding = 7) buffer Output {" NL
7981 						   "  int g_length[];" NL "};";
7982 
7983 		std::string expr =
7984 			NL "  g_length[0] = g_input0.length();" NL "  g_length[1] = g_input1.data.length();" NL
7985 			   "  g_length[2] = g_input23[0].data.length();" NL "  g_length[3] = g_input23[1].data.length();" NL
7986 			   "  g_length[4] = g_output0.data.length();" NL "  g_length[5] = g_input4.data.length();" NL
7987 			   "  g_length[6] = g_output1.data.length();";
7988 
7989 		std::string lastelemexpr =
7990 			NL "  g_output0.data[g_output0.data.length()-2] += g_output0.data[g_output0.data.length()-1];" NL
7991 			   "  g_output1.data[g_output1.data.length()-2] += g_output1.data[g_output1.data.length()-1];";
7992 
7993 		if (length_as_index)
7994 			expr += lastelemexpr;
7995 		if (stage == vertex)
7996 		{
7997 			os << decl << NL "void main() {" NL "  gl_Position = vec4(0,0,0,1);" << expr;
7998 		}
7999 		if (stage == fragment)
8000 		{
8001 			os << NL << decl << NL "void main() {" << expr;
8002 		}
8003 		if (stage == compute)
8004 		{
8005 			os << NL "layout(local_size_x = 1) in;" << decl << NL "void main() {" << expr;
8006 		}
8007 		os << NL "}";
8008 		return os.str();
8009 	}
8010 
Run()8011 	virtual long Run()
8012 	{
8013 		const int kSize = 100000;
8014 		const int kBufs = 8;
8015 		SetPath();
8016 		if (stage == vertex && !SupportedInVS(8))
8017 			return NOT_SUPPORTED;
8018 		GLint blocksC;
8019 		glGetIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &blocksC);
8020 		GLint minA;
8021 		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &minA);
8022 		if (blocksC < kBufs)
8023 			return NOT_SUPPORTED;
8024 		if (stage == vertex)
8025 		{
8026 			std::string glsl_vs = BuildShader();
8027 			std::string glsl_fs = BuildShaderPT(fragment);
8028 			m_program			= CreateProgram(glsl_vs, glsl_fs);
8029 		}
8030 		else if (stage == fragment)
8031 		{
8032 			std::string glsl_vs = BuildShaderPT(vertex);
8033 			std::string glsl_fs = BuildShader();
8034 			m_program			= CreateProgram(glsl_vs, glsl_fs);
8035 		}
8036 		else
8037 		{ // compute
8038 			std::string glsl_cs = BuildShader();
8039 			m_program			= CreateProgramCS(glsl_cs);
8040 		}
8041 		glLinkProgram(m_program);
8042 		if (!CheckProgram(m_program))
8043 			return ERROR;
8044 		glUseProgram(m_program);
8045 
8046 		glGenBuffers(kBufs, m_storage_buffer);
8047 		int sizes[kBufs] = { 7, 5, 3, 4, 23, 123, 419, 8 };
8048 
8049 		int columns[4][kBufs] = { { 1, 1, 1, 1, 1, 1, 1, 1 },   // vector: 1 col
8050 								  { 2, 3, 4, 4, 2, 3, 4, 1 },   // mat: # of cols
8051 								  { 2, 3, 4, 4, 3, 2, 2, 1 },   // RM mat: # of rows
8052 								  { 1, 1, 1, 1, 1, 1, 1, 1 } }; // structure: not used
8053 
8054 		int scalars[4][kBufs] = { { 4, 4, 4, 4, 2, 2, 4, 1 },   //vector: size
8055 								  { 2, 4, 4, 4, 4, 2, 2, 1 },   //matrix column_major: rows
8056 								  { 2, 4, 4, 4, 2, 4, 4, 1 },   //matrix row_major: columns
8057 								  { 1, 1, 1, 1, 1, 1, 1, 1 } }; //structure: not used
8058 
8059 		int mindw[4][kBufs] = { { 3, 4, 3, 3, 2, 2, 4, 1 }, // # of real 32bit items
8060 								{ 4, 9, 16, 16, 6, 6, 8, 1 },
8061 								{ 4, 9, 16, 16, 6, 6, 8, 1 },
8062 								{ 4, 11, 35, 35, 81, 127, 381, 1 } };
8063 		int std430struct[kBufs] = { 4, 16, 48, 48, 88, 68, 264, 1 };
8064 		int std140struct[kBufs] = { 4, 16, 60, 60, 144, 80, 432, 1 };
8065 		int bufsize[kBufs][2]   = { { 0 } };
8066 
8067 		std::vector<ivec4> data(kSize, ivec4(41));
8068 		for (int i = 0; i < kBufs; ++i)
8069 		{
8070 			if (layout == std430)
8071 			{
8072 				bufsize[i][1] = 4 * columns[etype][i] * scalars[etype][i];
8073 				if (etype == structure)
8074 				{
8075 					bufsize[i][1] = 4 * std430struct[i];
8076 				}
8077 			}
8078 			else if (layout == std140)
8079 			{
8080 				bufsize[i][1] = 4 * columns[etype][i] * 4;
8081 				if (etype == structure)
8082 				{
8083 					bufsize[i][1] = 4 * std140struct[i];
8084 				}
8085 			}
8086 			else
8087 			{
8088 				bufsize[i][1] = 4 * mindw[etype][i];
8089 			}
8090 			bufsize[i][0] = sizes[i] * bufsize[i][1];
8091 			if (i == kBufs - 1 || bind_seq == bindbasebefore)
8092 			{ // never trim feedback storage
8093 				glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8094 				glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8095 			}
8096 			else
8097 			{
8098 				glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[i]);
8099 				glBufferData(GL_SHADER_STORAGE_BUFFER, bufsize[i][0], &data[0], GL_DYNAMIC_COPY);
8100 				if (bind_seq == bindbaseafter)
8101 				{
8102 					glBindBufferBase(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i]);
8103 				}
8104 				else if (bind_seq == bindrangeoffset && 2 * bufsize[i][1] >= minA)
8105 				{
8106 					glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 2 * bufsize[i][1],
8107 									  bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8108 				}
8109 				else
8110 				{ // bind_seq == bindrangesize || 2*bufsize[i][1] < minA
8111 					glBindBufferRange(GL_SHADER_STORAGE_BUFFER, i, m_storage_buffer[i], 0,
8112 									  bufsize[i][0] - 2 * bufsize[i][1]); // without 2 elements
8113 				}
8114 			}
8115 		}
8116 
8117 		if (stage != compute)
8118 		{
8119 			glGenVertexArrays(1, &m_vertex_array);
8120 			glBindVertexArray(m_vertex_array);
8121 			glDrawArrays(GL_POINTS, 0, 1);
8122 		}
8123 		else
8124 		{
8125 			glDispatchCompute(1, 1, 1);
8126 		}
8127 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8128 
8129 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[kBufs - 1]);
8130 		int* dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizes[kBufs - 1], GL_MAP_READ_BIT);
8131 		if (!dataout)
8132 			return ERROR;
8133 		bool status = true;
8134 		for (int i = 0; i < kBufs - 1; ++i)
8135 		{
8136 			if (other_members)
8137 				sizes[i] -= 1; // space consumed by a pad
8138 			if (bind_seq == bindrangesize || bind_seq == bindrangeoffset)
8139 				sizes[i] -= 2; // space constrained by offset of range size
8140 			if ((layout == std140 || layout == std430) && dataout[i] != sizes[i])
8141 			{
8142 				m_context.getTestContext().getLog()
8143 					<< tcu::TestLog::Message << "Array " << i << " length is " << dataout[i] << " should be "
8144 					<< sizes[i] << tcu::TestLog::EndMessage;
8145 				status = false;
8146 			}
8147 			if ((layout == packed || layout == shared) && (dataout[i] > sizes[i]))
8148 			{
8149 				m_context.getTestContext().getLog()
8150 					<< tcu::TestLog::Message << "Array " << i << " length is " << dataout[i]
8151 					<< " should be not greater that " << sizes[i] << tcu::TestLog::EndMessage;
8152 				status = false;
8153 			}
8154 		}
8155 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8156 
8157 		if (length_as_index)
8158 		{
8159 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[4]);
8160 			dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[4][0], GL_MAP_READ_BIT);
8161 			if (!dataout)
8162 				return ERROR;
8163 			int i = (sizes[4] - 2) * columns[etype][4] * scalars[etype][4];
8164 			if (dataout[i] != 82)
8165 			{
8166 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 4 index " << i << " is "
8167 													<< dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8168 				status = false;
8169 			}
8170 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8171 			glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_storage_buffer[6]);
8172 			dataout = (int*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufsize[6][0], GL_MAP_READ_BIT);
8173 			if (!dataout)
8174 				return ERROR;
8175 			i = (sizes[6] - 2) * columns[etype][6] * scalars[etype][6];
8176 			if (dataout[i] != 82)
8177 			{
8178 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Array 6 index " << i << " is "
8179 													<< dataout[i] << " should be 82." << tcu::TestLog::EndMessage;
8180 				status = false;
8181 			}
8182 			glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8183 		}
8184 
8185 		if (!status)
8186 			return ERROR;
8187 
8188 		return NO_ERROR;
8189 	}
8190 
8191 public:
8192 	int  stage;
8193 	int  etype;
8194 	int  layout;
8195 	bool other_members;
8196 	int  bind_seq;
8197 	bool length_as_index;
8198 
AdvancedUnsizedArrayLength2()8199 	AdvancedUnsizedArrayLength2()
8200 		: m_program(0)
8201 		, m_vertex_array(0)
8202 		, stage(compute)
8203 		, etype(vector)
8204 		, layout(std430)
8205 		, other_members(false)
8206 		, bind_seq(bindbasebefore)
8207 		, length_as_index(false)
8208 	{
8209 	}
8210 };
8211 
8212 class AdvancedUnsizedArrayLength_cs_std430_vec_indexing : public AdvancedUnsizedArrayLength2
8213 {
8214 public:
SetPath()8215 	virtual void SetPath()
8216 	{
8217 		length_as_index = true;
8218 	}
8219 };
8220 
8221 class AdvancedUnsizedArrayLength_cs_std430_vec_after : public AdvancedUnsizedArrayLength2
8222 {
8223 public:
SetPath()8224 	virtual void SetPath()
8225 	{
8226 		bind_seq = bindbaseafter;
8227 	}
8228 };
8229 
8230 class AdvancedUnsizedArrayLength_cs_std430_vec_offset : public AdvancedUnsizedArrayLength2
8231 {
8232 public:
SetPath()8233 	virtual void SetPath()
8234 	{
8235 		bind_seq = bindrangeoffset;
8236 	}
8237 };
8238 
8239 class AdvancedUnsizedArrayLength_cs_std430_vec_size : public AdvancedUnsizedArrayLength2
8240 {
8241 public:
SetPath()8242 	virtual void SetPath()
8243 	{
8244 		bind_seq = bindrangesize;
8245 	}
8246 };
8247 
8248 class AdvancedUnsizedArrayLength_cs_std430_vec : public AdvancedUnsizedArrayLength2
8249 {
8250 public:
SetPath()8251 	virtual void SetPath()
8252 	{
8253 		etype = vector;
8254 	}
8255 };
8256 
8257 class AdvancedUnsizedArrayLength_cs_std430_matC : public AdvancedUnsizedArrayLength2
8258 {
8259 public:
SetPath()8260 	virtual void SetPath()
8261 	{
8262 		etype = matrix_cm;
8263 	}
8264 };
8265 
8266 class AdvancedUnsizedArrayLength_cs_std430_matR : public AdvancedUnsizedArrayLength2
8267 {
8268 public:
SetPath()8269 	virtual void SetPath()
8270 	{
8271 		etype = matrix_rm;
8272 	}
8273 };
8274 
8275 class AdvancedUnsizedArrayLength_cs_std430_struct : public AdvancedUnsizedArrayLength2
8276 {
8277 public:
SetPath()8278 	virtual void SetPath()
8279 	{
8280 		etype = structure;
8281 	}
8282 };
8283 
8284 class AdvancedUnsizedArrayLength_cs_std140_vec : public AdvancedUnsizedArrayLength2
8285 {
8286 public:
SetPath()8287 	virtual void SetPath()
8288 	{
8289 		stage  = compute;
8290 		layout = std140;
8291 	}
8292 };
8293 
8294 class AdvancedUnsizedArrayLength_cs_std140_matC : public AdvancedUnsizedArrayLength2
8295 {
8296 public:
SetPath()8297 	virtual void SetPath()
8298 	{
8299 		etype  = matrix_cm;
8300 		layout = std140;
8301 	}
8302 };
8303 
8304 class AdvancedUnsizedArrayLength_cs_std140_matR : public AdvancedUnsizedArrayLength2
8305 {
8306 public:
SetPath()8307 	virtual void SetPath()
8308 	{
8309 		etype  = matrix_rm;
8310 		layout = std140;
8311 	}
8312 };
8313 
8314 class AdvancedUnsizedArrayLength_cs_std140_struct : public AdvancedUnsizedArrayLength2
8315 {
8316 public:
SetPath()8317 	virtual void SetPath()
8318 	{
8319 		etype  = structure;
8320 		layout = std140;
8321 	}
8322 };
8323 
8324 class AdvancedUnsizedArrayLength_cs_packed_vec : public AdvancedUnsizedArrayLength2
8325 {
8326 public:
SetPath()8327 	virtual void SetPath()
8328 	{
8329 		etype  = vector;
8330 		layout = packed;
8331 	}
8332 };
8333 
8334 class AdvancedUnsizedArrayLength_cs_packed_matC : public AdvancedUnsizedArrayLength2
8335 {
8336 public:
SetPath()8337 	virtual void SetPath()
8338 	{
8339 		etype  = matrix_cm;
8340 		layout = packed;
8341 	}
8342 };
8343 
8344 class AdvancedUnsizedArrayLength_cs_shared_matR : public AdvancedUnsizedArrayLength2
8345 {
8346 public:
SetPath()8347 	virtual void SetPath()
8348 	{
8349 		etype  = matrix_rm;
8350 		layout = shared;
8351 	}
8352 };
8353 
8354 class AdvancedUnsizedArrayLength_fs_std430_vec : public AdvancedUnsizedArrayLength2
8355 {
8356 public:
SetPath()8357 	virtual void SetPath()
8358 	{
8359 		stage  = fragment;
8360 		etype  = vector;
8361 		layout = std430;
8362 	}
8363 };
8364 
8365 class AdvancedUnsizedArrayLength_fs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8366 {
8367 public:
SetPath()8368 	virtual void SetPath()
8369 	{
8370 		stage		  = fragment;
8371 		etype		  = matrix_cm;
8372 		layout		  = std430;
8373 		other_members = true;
8374 	}
8375 };
8376 
8377 class AdvancedUnsizedArrayLength_fs_std140_matR : public AdvancedUnsizedArrayLength2
8378 {
8379 public:
SetPath()8380 	virtual void SetPath()
8381 	{
8382 		stage  = fragment;
8383 		etype  = matrix_rm;
8384 		layout = std140;
8385 	}
8386 };
8387 
8388 class AdvancedUnsizedArrayLength_fs_std140_struct : public AdvancedUnsizedArrayLength2
8389 {
8390 public:
SetPath()8391 	virtual void SetPath()
8392 	{
8393 		stage  = fragment;
8394 		etype  = structure;
8395 		layout = std140;
8396 	}
8397 };
8398 
8399 class AdvancedUnsizedArrayLength_vs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8400 {
8401 public:
SetPath()8402 	virtual void SetPath()
8403 	{
8404 		stage		  = vertex;
8405 		etype		  = vector;
8406 		layout		  = std430;
8407 		other_members = true;
8408 	}
8409 };
8410 
8411 class AdvancedUnsizedArrayLength_vs_std140_matC : public AdvancedUnsizedArrayLength2
8412 {
8413 public:
SetPath()8414 	virtual void SetPath()
8415 	{
8416 		stage  = vertex;
8417 		etype  = matrix_cm;
8418 		layout = std140;
8419 	}
8420 };
8421 
8422 class AdvancedUnsizedArrayLength_vs_packed_matR : public AdvancedUnsizedArrayLength2
8423 {
8424 public:
SetPath()8425 	virtual void SetPath()
8426 	{
8427 		stage  = vertex;
8428 		etype  = matrix_rm;
8429 		layout = packed;
8430 	}
8431 };
8432 
8433 class AdvancedUnsizedArrayLength_vs_std140_struct : public AdvancedUnsizedArrayLength2
8434 {
8435 public:
SetPath()8436 	virtual void SetPath()
8437 	{
8438 		stage  = vertex;
8439 		etype  = structure;
8440 		layout = std140;
8441 	}
8442 };
8443 
8444 class AdvancedUnsizedArrayLength_cs_std430_vec_pad : public AdvancedUnsizedArrayLength2
8445 {
8446 public:
SetPath()8447 	virtual void SetPath()
8448 	{
8449 		etype		  = vector;
8450 		other_members = true;
8451 	}
8452 };
8453 
8454 class AdvancedUnsizedArrayLength_cs_std430_matC_pad : public AdvancedUnsizedArrayLength2
8455 {
8456 public:
SetPath()8457 	virtual void SetPath()
8458 	{
8459 		etype		  = matrix_cm;
8460 		other_members = true;
8461 	}
8462 };
8463 
8464 class AdvancedUnsizedArrayLength_cs_std140_matR_pad : public AdvancedUnsizedArrayLength2
8465 {
8466 public:
SetPath()8467 	virtual void SetPath()
8468 	{
8469 		etype		  = matrix_rm;
8470 		layout		  = std140;
8471 		other_members = true;
8472 	}
8473 };
8474 
8475 class AdvancedUnsizedArrayLength_cs_std430_struct_pad : public AdvancedUnsizedArrayLength2
8476 {
8477 public:
SetPath()8478 	virtual void SetPath()
8479 	{
8480 		etype		  = structure;
8481 		other_members = true;
8482 	}
8483 };
8484 
8485 //-----------------------------------------------------------------------------
8486 // 2.8 AdvancedMatrix
8487 //-----------------------------------------------------------------------------
8488 
8489 class AdvancedMatrix : public ShaderStorageBufferObjectBase
8490 {
8491 	GLuint m_program;
8492 	GLuint m_storage_buffer[3];
8493 	GLuint m_vertex_array;
8494 	GLuint m_vertex_buffer;
8495 	GLuint m_fbo, m_rt;
8496 
Setup()8497 	virtual long Setup()
8498 	{
8499 		m_program = 0;
8500 		memset(m_storage_buffer, 0, sizeof(m_storage_buffer));
8501 		m_vertex_array  = 0;
8502 		m_vertex_buffer = 0;
8503 		glGenFramebuffers(1, &m_fbo);
8504 		glGenTextures(1, &m_rt);
8505 		return NO_ERROR;
8506 	}
8507 
Run()8508 	virtual long Run()
8509 	{
8510 		if (!SupportedInVS(2))
8511 			return NOT_SUPPORTED;
8512 
8513 		const char* const glsl_vs =
8514 			NL "layout(location = 0) in vec4 g_position;" NL "out StageData {" NL "  flat int instance_id;" NL
8515 			   "} vs_out;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL "  mat3x4 g_transform[4];" NL
8516 			   "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
8517 			   "layout(binding = 1, std430) readonly buffer Buffer1 {" NL "  mat4 color;" NL "} g_buffer1;" NL
8518 			   "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8519 			   "  gl_Position = vec4(transpose(g_transform[gl_InstanceID]) * g_position, 1);" NL
8520 			   "  g_color[gl_InstanceID] = g_buffer1.color[gl_InstanceID].rgb;" NL
8521 			   "  if (gl_VertexID == 0 && gl_InstanceID == 0) {" NL "    g_data0[1][1] = 1.0;" NL
8522 			   "    g_data0[g_index1][g_index2] += 3.0;" NL "  }" NL "  memoryBarrier();" NL
8523 			   "  vs_out.instance_id = gl_InstanceID;" NL "}";
8524 
8525 		const char* const glsl_fs =
8526 			NL "in StageData {" NL "  flat int instance_id;" NL "} fs_in;" NL
8527 			   "layout(location = 0) out vec4 g_ocolor;" NL "layout(binding = 0, std430) coherent buffer Buffer0 {" NL
8528 			   "  mat3x4 g_transform[4];" NL "  mat4x3 g_color;" NL "  mat3 g_data0;" NL "};" NL
8529 			   "uniform int g_index1 = 1;" NL "uniform int g_index2 = 2;" NL "void main() {" NL
8530 			   "  if (g_data0[g_index1][g_index1] != 1.0) g_ocolor = vec4(0);" NL
8531 			   "  else if (g_data0[g_index1][g_index2] != 3.0) g_ocolor = vec4(0);" NL
8532 			   "  else g_ocolor = vec4(g_color[fs_in.instance_id], 1);" NL "}";
8533 
8534 		m_program = CreateProgram(glsl_vs, glsl_fs);
8535 		glLinkProgram(m_program);
8536 		if (!CheckProgram(m_program))
8537 			return ERROR;
8538 
8539 		glGenBuffers(3, m_storage_buffer);
8540 
8541 		/* transform buffer */
8542 		{
8543 			float data[48 + 16 + 12 + 16] = {
8544 				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,
8545 				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,
8546 				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,
8547 			};
8548 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer[0]);
8549 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8550 		}
8551 		/* transform buffer */
8552 		{
8553 			float data[16] = {
8554 				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,
8555 			};
8556 			glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_storage_buffer[1]);
8557 			glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8558 		}
8559 		/* vertex buffer */
8560 		{
8561 			float data[8] = { -0.4f, -0.4f, 0.4f, -0.4f, -0.4f, 0.4f, 0.4f, 0.4f };
8562 			glGenBuffers(1, &m_vertex_buffer);
8563 			glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8564 			glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
8565 			glBindBuffer(GL_ARRAY_BUFFER, 0);
8566 		}
8567 
8568 		glBindTexture(GL_TEXTURE_2D, m_rt);
8569 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8570 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8571 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 100, 100);
8572 		glBindTexture(GL_TEXTURE_2D, 0);
8573 		glViewport(0, 0, 100, 100);
8574 		glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
8575 		glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_rt, 0);
8576 
8577 		glGenVertexArrays(1, &m_vertex_array);
8578 		glBindVertexArray(m_vertex_array);
8579 		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);
8580 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
8581 		glBindBuffer(GL_ARRAY_BUFFER, 0);
8582 		glEnableVertexAttribArray(0);
8583 		glBindVertexArray(0);
8584 
8585 		glClear(GL_COLOR_BUFFER_BIT);
8586 		glUseProgram(m_program);
8587 		glBindVertexArray(m_vertex_array);
8588 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 4);
8589 
8590 		if (!ValidateWindow4Quads(vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1), vec3(1, 1, 0)))
8591 		{
8592 			return ERROR;
8593 		}
8594 		return NO_ERROR;
8595 	}
8596 
Cleanup()8597 	virtual long Cleanup()
8598 	{
8599 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
8600 		glUseProgram(0);
8601 		glDeleteProgram(m_program);
8602 		glDeleteBuffers(3, m_storage_buffer);
8603 		glDeleteBuffers(1, &m_vertex_buffer);
8604 		glDeleteVertexArrays(1, &m_vertex_array);
8605 		glDeleteFramebuffers(1, &m_fbo);
8606 		glDeleteTextures(1, &m_rt);
8607 		return NO_ERROR;
8608 	}
8609 };
8610 
8611 class AdvancedMatrixCS : public ShaderStorageBufferObjectBase
8612 {
8613 	GLuint m_program;
8614 	GLuint m_storage_buffer;
8615 
Setup()8616 	virtual long Setup()
8617 	{
8618 		m_program		 = 0;
8619 		m_storage_buffer = 0;
8620 		return NO_ERROR;
8621 	}
8622 
Run()8623 	virtual long Run()
8624 	{
8625 		bool			  status = true;
8626 		const char* const glsl_cs =
8627 			NL "layout(local_size_x = 1) in;" NL "layout(std430) buffer Buffer {" NL "  mat4x3 dst4x3;" NL
8628 			   "  mat4 dst4;" NL "  mat4 src4;" NL "} b;" NL "uniform int g_index1;" NL "uniform int g_index2;" NL
8629 			   "void main() {" NL "  b.dst4x3[gl_LocalInvocationIndex] = b.src4[gl_LocalInvocationIndex].rgb;" NL
8630 			   "  b.dst4x3[gl_LocalInvocationIndex + 1u] = b.src4[gl_LocalInvocationIndex + 1u].aar;" NL
8631 			   "  b.dst4[g_index2][g_index1] = 17.0;" NL "  b.dst4[g_index2][g_index1] += 6.0;" NL
8632 			   "  b.dst4[3][0] = b.src4[3][0] != 44.0 ? 3.0 : 7.0;" NL "  b.dst4[3][1] = b.src4[3][1];" NL "}";
8633 		m_program = CreateProgramCS(glsl_cs);
8634 		glLinkProgram(m_program);
8635 		if (!CheckProgram(m_program))
8636 			return ERROR;
8637 
8638 		glGenBuffers(1, &m_storage_buffer);
8639 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_storage_buffer);
8640 		GLfloat data[16 + 16 + 16];
8641 		for (int i  = 0; i < 32; ++i)
8642 			data[i] = 0.0f;
8643 		for (int i  = 32; i < 48; ++i)
8644 			data[i] = (GLfloat)i;
8645 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), &data[0], GL_DYNAMIC_DRAW);
8646 
8647 		glUseProgram(m_program);
8648 		glUniform1i(glGetUniformLocation(m_program, "g_index1"), 1);
8649 		glUniform1i(glGetUniformLocation(m_program, "g_index2"), 2);
8650 		glDispatchCompute(1, 1, 1);
8651 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
8652 		GLfloat* out_data = (GLfloat*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(data), GL_MAP_READ_BIT);
8653 		if (!out_data)
8654 			return ERROR;
8655 
8656 		GLfloat expected[32] = { 32.0f, 33.0f, 34.0f, 0.0f, 39.0f, 39.0f, 36.0f, 0.0f,
8657 								 0.0f,  0.0f,  0.0f,  0.0f, 0.0f,  0.0f,  0.0f,  0.0f,
8658 
8659 								 0.0f,  0.0f,  0.0f,  0.0f, 0.0f,  0.0f,  0.0f,  0.0f,
8660 								 0.0f,  23.0f, 0.0f,  0.0f, 7.0f,  45.0f, 0.0f,  0.0f };
8661 		for (int i = 0; i < 32; ++i)
8662 		{
8663 			if (out_data[i] != expected[i])
8664 			{
8665 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Received: " << out_data[i]
8666 													<< ", but expected: " << expected[i] << tcu::TestLog::EndMessage;
8667 				status = false;
8668 			}
8669 		}
8670 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8671 		if (status)
8672 			return NO_ERROR;
8673 		else
8674 			return ERROR;
8675 	}
8676 
Cleanup()8677 	virtual long Cleanup()
8678 	{
8679 		glUseProgram(0);
8680 		glDeleteProgram(m_program);
8681 		glDeleteBuffers(1, &m_storage_buffer);
8682 		return NO_ERROR;
8683 	}
8684 };
8685 //-----------------------------------------------------------------------------
8686 // 4.1.1 NegativeAPIBind
8687 //-----------------------------------------------------------------------------
8688 
8689 class NegativeAPIBind : public ShaderStorageBufferObjectBase
8690 {
Run()8691 	virtual long Run()
8692 	{
8693 		GLint bindings;
8694 		GLint alignment;
8695 		glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8696 		glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &alignment);
8697 
8698 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, bindings, 0);
8699 		if (glGetError() != GL_INVALID_VALUE)
8700 		{
8701 			m_context.getTestContext().getLog()
8702 				<< tcu::TestLog::Message
8703 				<< "INVALID_VALUE is generated by BindBufferBase if <target> is\n"
8704 				   "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8705 				   "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8706 				<< tcu::TestLog::EndMessage;
8707 			return ERROR;
8708 		}
8709 
8710 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, bindings, 0, 0, 0);
8711 		if (glGetError() != GL_INVALID_VALUE)
8712 		{
8713 			m_context.getTestContext().getLog()
8714 				<< tcu::TestLog::Message
8715 				<< "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8716 				   "SHADER_STORAGE_BUFFER and <index> is greater than or equal to the value of\n"
8717 				   "MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8718 				<< tcu::TestLog::EndMessage;
8719 			return ERROR;
8720 		}
8721 
8722 		glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 0, alignment - 1, 0);
8723 		if (glGetError() != GL_INVALID_VALUE)
8724 		{
8725 			m_context.getTestContext().getLog()
8726 				<< tcu::TestLog::Message << "INVALID_VALUE is generated by BindBufferRange if <target> is\n"
8727 											"SHADER_STORAGE_BUFFER and <offset> is not a multiple of the value of\n"
8728 											"SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT."
8729 				<< tcu::TestLog::EndMessage;
8730 			return ERROR;
8731 		}
8732 
8733 		return NO_ERROR;
8734 	}
8735 };
8736 //-----------------------------------------------------------------------------
8737 // 4.1.2 NegativeAPIBlockBinding
8738 //-----------------------------------------------------------------------------
8739 
8740 class NegativeAPIBlockBinding : public ShaderStorageBufferObjectBase
8741 {
Run()8742 	virtual long Run()
8743 	{
8744 		if (!SupportedInVS(1))
8745 			return NOT_SUPPORTED;
8746 		GLint bindings;
8747 		glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8748 
8749 		const char* const glsl_vs =
8750 			"#version 430 core" NL "buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8751 		const GLuint sh = glCreateShader(GL_VERTEX_SHADER);
8752 		glShaderSource(sh, 1, &glsl_vs, NULL);
8753 		glCompileShader(sh);
8754 
8755 		const GLuint p = glCreateProgram();
8756 		glAttachShader(p, sh);
8757 		glDeleteShader(sh);
8758 		glLinkProgram(p);
8759 
8760 		glShaderStorageBlockBinding(p, 0, bindings);
8761 		if (glGetError() != GL_INVALID_VALUE)
8762 		{
8763 			m_context.getTestContext().getLog()
8764 				<< tcu::TestLog::Message << "An INVALID_VALUE error is generated if storageBlockBinding is\n"
8765 											"greater than or equal to the value of MAX_SHADER_STORAGE_BUFFER_BINDINGS."
8766 				<< tcu::TestLog::EndMessage;
8767 			glDeleteProgram(p);
8768 			return ERROR;
8769 		}
8770 
8771 		glShaderStorageBlockBinding(p, 1, 0);
8772 		if (glGetError() != GL_INVALID_VALUE)
8773 		{
8774 			m_context.getTestContext().getLog()
8775 				<< tcu::TestLog::Message << "An INVALID_VALUE error is generated if storageBlockIndex is not an\n"
8776 											"active shader storage block index in program."
8777 				<< tcu::TestLog::EndMessage;
8778 			glDeleteProgram(p);
8779 			return ERROR;
8780 		}
8781 
8782 		glShaderStorageBlockBinding(0, 0, 0);
8783 		if (glGetError() != GL_INVALID_VALUE)
8784 		{
8785 			m_context.getTestContext().getLog()
8786 				<< tcu::TestLog::Message << "An INVALID_VALUE error is generated if program is not the name of "
8787 											"either a program or shader object."
8788 				<< tcu::TestLog::EndMessage;
8789 			glDeleteProgram(p);
8790 			return ERROR;
8791 		}
8792 
8793 		glShaderStorageBlockBinding(sh, 0, 0);
8794 		if (glGetError() != GL_INVALID_OPERATION)
8795 		{
8796 			m_context.getTestContext().getLog()
8797 				<< tcu::TestLog::Message
8798 				<< "An INVALID_OPERATION error is generated if program is the name of a shader object."
8799 				<< tcu::TestLog::EndMessage;
8800 			glDeleteProgram(p);
8801 			return ERROR;
8802 		}
8803 
8804 		glDeleteProgram(p);
8805 		return NO_ERROR;
8806 	}
8807 };
8808 //-----------------------------------------------------------------------------
8809 // 4.2.1 NegativeGLSLCompileTime
8810 //-----------------------------------------------------------------------------
8811 
8812 class NegativeGLSLCompileTime : public ShaderStorageBufferObjectBase
8813 {
Shader1(int binding)8814 	static std::string Shader1(int binding)
8815 	{
8816 		std::stringstream ss;
8817 		ss << NL "layout(binding = " << binding
8818 		   << ") buffer Buffer {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}";
8819 		return ss.str();
8820 	}
8821 
Shader2(int binding)8822 	static std::string Shader2(int binding)
8823 	{
8824 		std::stringstream ss;
8825 		ss << NL "layout(binding = " << binding
8826 		   << ") buffer Buffer {" NL "  int x;" NL "} g_array[4];" NL "void main() {" NL "  g_array[0].x = 0;" NL
8827 			  "  g_array[1].x = 0;" NL "  g_array[2].x = 0;" NL "  g_array[3].x = 0;" NL "}";
8828 		return ss.str();
8829 	}
8830 
Run()8831 	virtual long Run()
8832 	{
8833 		GLint bindings;
8834 		glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &bindings);
8835 
8836 		//  initialization of buffer block member 'x' not allowed
8837 		if (!Compile(NL "buffer Buffer { int x = 10; };" NL "void main() {" NL "  x = 0;" NL "}"))
8838 			return ERROR;
8839 
8840 		//  syntax error, unexpected '-', expecting integer constant or unsigned integer constant at token "-"
8841 		if (!Compile(Shader1(-1)))
8842 			return ERROR;
8843 		//  invalid value 96 for layout specifier 'binding'
8844 		if (!Compile(Shader1(bindings)))
8845 			return ERROR;
8846 
8847 		//  invalid value 98 for layout specifier 'binding'
8848 		if (!Compile(Shader2(bindings - 2)))
8849 			return ERROR;
8850 
8851 		//  OpenGL does not allow declaring buffer variable 'x' in the global scope. Use buffer blocks instead
8852 		if (!Compile(NL "buffer int x;" NL "void main() {" NL "  x = 0;" NL "}"))
8853 			return ERROR;
8854 
8855 		// OpenGL requires buffer variables to be declared in a shader storage block in the global scope
8856 		if (!Compile(NL "buffer Buffer { int y; };" NL "void main() {" NL "  y = 0;" NL "  buffer int x = 0;" NL "}"))
8857 			return ERROR;
8858 
8859 		//  OpenGL does not allow a parameter to be a buffer
8860 		if (!Compile(NL "buffer Buffer { int y; };" NL "void Modify(buffer int a) {" NL "  atomicAdd(a, 1);" NL "}" NL
8861 						"void main() {" NL "  Modify(y);" NL "}"))
8862 			return ERROR;
8863 
8864 		//  layout specifier 'std430', incompatible with 'uniform blocks'
8865 		if (!Compile(NL "layout(std430) uniform UBO { int x; };" NL "buffer SSBO { int y; };" NL "void main() {" NL
8866 						"  y = x;" NL "}"))
8867 			return ERROR;
8868 
8869 		//  unknown layout specifier 'std430'
8870 		if (!Compile(NL "buffer SSBO {" NL "  layout(std430) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8871 			return ERROR;
8872 
8873 		//  unknown layout specifier 'binding = 1'
8874 		if (!Compile(NL "buffer SSBO {" NL "  layout(binding = 1) int x;" NL "};" NL "void main() {" NL "  x = 0;" NL
8875 						"}"))
8876 			return ERROR;
8877 
8878 		//  OpenGL does not allow writing to readonly variable 'x'
8879 		if (!Compile(NL "readonly buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL "  x = 0;" NL "}"))
8880 			return ERROR;
8881 
8882 		//  OpenGL does not allow reading writeonly variable 'y'
8883 		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "writeonly buffer SSBO2 {" NL "  int y;" NL "};" NL
8884 						"void main() {" NL "  x = y;" NL "}"))
8885 			return ERROR;
8886 
8887 		//  OpenGL does not allow writing to readonly variable 'z'
8888 		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "buffer SSBO2 {" NL "  writeonly int y;" NL
8889 						"  readonly int z;" NL "};" NL "void main() {" NL "  x = y;" NL "  z = 0;" NL "}"))
8890 			return ERROR;
8891 
8892 		//  OpenGL does not allow having both readonly and writeonly qualifiers on a variable
8893 		if (!Compile(NL "buffer SSBO {" NL "  int x;" NL "};" NL "readonly buffer SSBO2 {" NL "  writeonly int y;" NL
8894 						"};" NL "void main() {" NL "  x = y;" NL "}"))
8895 			return ERROR;
8896 
8897 		// ["layout(binding = 1) buffer;" should cause compile-time error
8898 		if (!Compile(NL "layout(binding = 1) buffer;" NL "buffer SSBO {" NL "  int x;" NL "};" NL "void main() {" NL
8899 						"  x = 0;" NL "}"))
8900 			return ERROR;
8901 
8902 		// ["  atomicAdd(y, 2);"  should cause compile-time error
8903 		if (!Compile(NL "buffer Buffer { int x; };" NL "int y;" NL "void main() {" NL "  atomicAdd(x, 1);" NL
8904 						"  atomicAdd(y, 2);" //
8905 					 NL "}"))
8906 			return ERROR;
8907 
8908 		if (!Compile( // can't construct vector from an array
8909 				NL "buffer b {" NL "  vec4 x[10];" NL "};" NL "void main() {" NL "  vec4 y = vec4(x);" NL "}"))
8910 			return ERROR;
8911 
8912 		return NO_ERROR;
8913 	}
8914 
Compile(const std::string & source)8915 	bool Compile(const std::string& source)
8916 	{
8917 		const char* const csVer  = "#version 430 core";
8918 		const char* const src[2] = { csVer, source.c_str() };
8919 		const GLuint	  sh	 = glCreateShader(GL_FRAGMENT_SHADER);
8920 		glShaderSource(sh, 2, src, NULL);
8921 		glCompileShader(sh);
8922 
8923 		GLchar log[1024];
8924 		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
8925 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
8926 											<< log << tcu::TestLog::EndMessage;
8927 
8928 		GLint status;
8929 		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8930 		glDeleteShader(sh);
8931 
8932 		if (status == GL_TRUE)
8933 		{
8934 			m_context.getTestContext().getLog()
8935 				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
8936 			return false;
8937 		}
8938 
8939 		return true;
8940 	}
8941 };
8942 
8943 //-----------------------------------------------------------------------------
8944 // 4.2.2 NegativeGLSLLinkTime
8945 //-----------------------------------------------------------------------------
8946 class NegativeGLSLLinkTime : public ShaderStorageBufferObjectBase
8947 {
Run()8948 	virtual long Run()
8949 	{
8950 		//   declaration of "x" conflicts with previous declaration at 0(4)
8951 		//   declaration of "Buffer" conflicts with previous declaration at 0(4)
8952 		if (!Link("#version 430 core" NL "buffer Buffer { int x; };" NL "void Run();" NL "void main() {" NL
8953 				  "  Run();" NL "  x += 2;" NL "}",
8954 				  "#version 430 core" NL "buffer Buffer { uint x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8955 			return ERROR;
8956 
8957 		//  declaration of "Buffer" conflicts with previous declaration at 0(4)
8958 		if (!Link("#version 430 core" NL "buffer Buffer { int x; int y; };" NL "void Run();" NL "void main() {" NL
8959 				  "  Run();" NL "  x += 2;" NL "}",
8960 				  "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8961 			return ERROR;
8962 
8963 		//  declaration of "Buffer" conflicts with previous declaration at 0(4)
8964 		if (!Link("#version 430 core" NL "buffer Buffer { int y; };" NL "void Run();" NL "void main() {" NL
8965 				  "  Run();" NL "  y += 2;" NL "}",
8966 				  "#version 430 core" NL "buffer Buffer { int x; };" NL "void Run() {" NL "  x += 3;" NL "}"))
8967 			return ERROR;
8968 
8969 		//  declaration of "g_buffer" conflicts with previous declaration at 0(4)
8970 		//  declaration of "Buffer" conflicts with previous declaration at 0(4)
8971 		if (!Link("#version 430 core" NL "buffer Buffer { int x; } g_buffer[2];" NL "void Run();" NL "void main() {" NL
8972 				  "  Run();" NL "  g_buffer[0].x += 2;" NL "}",
8973 				  "#version 430 core" NL "buffer Buffer { int x; } g_buffer[3];" NL "void Run() {" NL
8974 				  "  g_buffer[1].x += 3;" NL "}"))
8975 			return ERROR;
8976 
8977 		return NO_ERROR;
8978 	}
8979 
Link(const std::string & cs0,const std::string & cs1)8980 	bool Link(const std::string& cs0, const std::string& cs1)
8981 	{
8982 		const GLuint p = glCreateProgram();
8983 
8984 		/* shader 0 */
8985 		{
8986 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
8987 			glAttachShader(p, sh);
8988 			glDeleteShader(sh);
8989 			const char* const src = cs0.c_str();
8990 			glShaderSource(sh, 1, &src, NULL);
8991 			glCompileShader(sh);
8992 
8993 			GLint status;
8994 			glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
8995 			if (status == GL_FALSE)
8996 			{
8997 				glDeleteProgram(p);
8998 				m_context.getTestContext().getLog()
8999 					<< tcu::TestLog::Message << "VS0 compilation should be ok." << tcu::TestLog::EndMessage;
9000 				return false;
9001 			}
9002 		}
9003 		/* shader 1 */
9004 		{
9005 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
9006 			glAttachShader(p, sh);
9007 			glDeleteShader(sh);
9008 			const char* const src = cs1.c_str();
9009 			glShaderSource(sh, 1, &src, NULL);
9010 			glCompileShader(sh);
9011 
9012 			GLint status;
9013 			glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
9014 			if (status == GL_FALSE)
9015 			{
9016 				glDeleteProgram(p);
9017 				m_context.getTestContext().getLog()
9018 					<< tcu::TestLog::Message << "VS1 compilation should be ok." << tcu::TestLog::EndMessage;
9019 				return false;
9020 			}
9021 		}
9022 
9023 		glLinkProgram(p);
9024 
9025 		GLchar log[1024];
9026 		glGetProgramInfoLog(p, sizeof(log), NULL, log);
9027 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
9028 											<< log << tcu::TestLog::EndMessage;
9029 
9030 		GLint status;
9031 		glGetProgramiv(p, GL_LINK_STATUS, &status);
9032 		glDeleteProgram(p);
9033 
9034 		if (status == GL_TRUE)
9035 		{
9036 			m_context.getTestContext().getLog()
9037 				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
9038 			return false;
9039 		}
9040 
9041 		return true;
9042 	}
9043 };
9044 
9045 } // anonymous namespace
9046 
ShaderStorageBufferObjectTests(deqp::Context & context)9047 ShaderStorageBufferObjectTests::ShaderStorageBufferObjectTests(deqp::Context& context)
9048 	: TestCaseGroup(context, "shader_storage_buffer_object", "")
9049 {
9050 }
9051 
~ShaderStorageBufferObjectTests(void)9052 ShaderStorageBufferObjectTests::~ShaderStorageBufferObjectTests(void)
9053 {
9054 }
9055 
init()9056 void ShaderStorageBufferObjectTests::init()
9057 {
9058 	using namespace deqp;
9059 
9060 	addChild(new TestSubcase(m_context, "basic-basic", TestSubcase::Create<BasicBasic>));
9061 	addChild(new TestSubcase(m_context, "basic-basic-cs", TestSubcase::Create<BasicBasicCS>));
9062 	addChild(new TestSubcase(m_context, "basic-max", TestSubcase::Create<BasicMax>));
9063 	addChild(new TestSubcase(m_context, "basic-binding", TestSubcase::Create<BasicBinding>));
9064 	addChild(new TestSubcase(m_context, "basic-syntax", TestSubcase::Create<BasicSyntax>));
9065 	addChild(new TestSubcase(m_context, "basic-syntaxSSO", TestSubcase::Create<BasicSyntaxSSO>));
9066 	addChild(new TestSubcase(m_context, "basic-std430Layout-case1-vs", TestSubcase::Create<BasicStd430LayoutCase1VS>));
9067 	addChild(new TestSubcase(m_context, "basic-std430Layout-case1-cs", TestSubcase::Create<BasicStd430LayoutCase1CS>));
9068 	addChild(new TestSubcase(m_context, "basic-std430Layout-case2-vs", TestSubcase::Create<BasicStd430LayoutCase2VS>));
9069 	addChild(new TestSubcase(m_context, "basic-std430Layout-case2-cs", TestSubcase::Create<BasicStd430LayoutCase2CS>));
9070 	addChild(new TestSubcase(m_context, "basic-std430Layout-case3-vs", TestSubcase::Create<BasicStd430LayoutCase3VS>));
9071 	addChild(new TestSubcase(m_context, "basic-std430Layout-case3-cs", TestSubcase::Create<BasicStd430LayoutCase3CS>));
9072 	addChild(new TestSubcase(m_context, "basic-std430Layout-case4-vs", TestSubcase::Create<BasicStd430LayoutCase4VS>));
9073 	addChild(new TestSubcase(m_context, "basic-std430Layout-case4-cs", TestSubcase::Create<BasicStd430LayoutCase4CS>));
9074 	addChild(new TestSubcase(m_context, "basic-std430Layout-case5-vs", TestSubcase::Create<BasicStd430LayoutCase5VS>));
9075 	addChild(new TestSubcase(m_context, "basic-std430Layout-case5-cs", TestSubcase::Create<BasicStd430LayoutCase5CS>));
9076 	addChild(new TestSubcase(m_context, "basic-std430Layout-case6-vs", TestSubcase::Create<BasicStd430LayoutCase6VS>));
9077 	addChild(new TestSubcase(m_context, "basic-std430Layout-case6-cs", TestSubcase::Create<BasicStd430LayoutCase6CS>));
9078 	addChild(new TestSubcase(m_context, "basic-std430Layout-case7-vs", TestSubcase::Create<BasicStd430LayoutCase7VS>));
9079 	addChild(new TestSubcase(m_context, "basic-std430Layout-case7-cs", TestSubcase::Create<BasicStd430LayoutCase7CS>));
9080 	addChild(new TestSubcase(m_context, "basic-std140Layout-case1-vs", TestSubcase::Create<BasicStd140LayoutCase1VS>));
9081 	addChild(new TestSubcase(m_context, "basic-std140Layout-case1-cs", TestSubcase::Create<BasicStd140LayoutCase1CS>));
9082 	addChild(new TestSubcase(m_context, "basic-std140Layout-case2-vs", TestSubcase::Create<BasicStd140LayoutCase2VS>));
9083 	addChild(new TestSubcase(m_context, "basic-std140Layout-case2-cs", TestSubcase::Create<BasicStd140LayoutCase2CS>));
9084 	addChild(new TestSubcase(m_context, "basic-std140Layout-case3-vs", TestSubcase::Create<BasicStd140LayoutCase3VS>));
9085 	addChild(new TestSubcase(m_context, "basic-std140Layout-case3-cs", TestSubcase::Create<BasicStd140LayoutCase3CS>));
9086 	addChild(new TestSubcase(m_context, "basic-std140Layout-case4-vs", TestSubcase::Create<BasicStd140LayoutCase4VS>));
9087 	addChild(new TestSubcase(m_context, "basic-std140Layout-case4-cs", TestSubcase::Create<BasicStd140LayoutCase4CS>));
9088 	addChild(new TestSubcase(m_context, "basic-std140Layout-case5-vs", TestSubcase::Create<BasicStd140LayoutCase5VS>));
9089 	addChild(new TestSubcase(m_context, "basic-std140Layout-case5-cs", TestSubcase::Create<BasicStd140LayoutCase5CS>));
9090 	addChild(new TestSubcase(m_context, "basic-std140Layout-case6-vs", TestSubcase::Create<BasicStd140LayoutCase6VS>));
9091 	addChild(new TestSubcase(m_context, "basic-std140Layout-case6-cs", TestSubcase::Create<BasicStd140LayoutCase6CS>));
9092 	addChild(new TestSubcase(m_context, "basic-atomic-case1", TestSubcase::Create<BasicAtomicCase1>));
9093 	addChild(new TestSubcase(m_context, "basic-atomic-case1-cs", TestSubcase::Create<BasicAtomicCase1CS>));
9094 	addChild(new TestSubcase(m_context, "basic-atomic-case2", TestSubcase::Create<BasicAtomicCase2>));
9095 	addChild(new TestSubcase(m_context, "basic-atomic-case3", TestSubcase::Create<BasicAtomicCase3>));
9096 	addChild(new TestSubcase(m_context, "basic-atomic-case3-cs", TestSubcase::Create<BasicAtomicCase3CS>));
9097 	addChild(new TestSubcase(m_context, "basic-atomic-case4", TestSubcase::Create<BasicAtomicCase4>));
9098 	addChild(new TestSubcase(m_context, "basic-atomic-case4-cs", TestSubcase::Create<BasicAtomicCase4CS>));
9099 	addChild(new TestSubcase(m_context, "basic-stdLayout-case1-vs", TestSubcase::Create<BasicStdLayoutCase1VS>));
9100 	addChild(new TestSubcase(m_context, "basic-stdLayout-case1-cs", TestSubcase::Create<BasicStdLayoutCase1CS>));
9101 	addChild(new TestSubcase(m_context, "basic-stdLayout-case2-vs", TestSubcase::Create<BasicStdLayoutCase2VS>));
9102 	addChild(new TestSubcase(m_context, "basic-stdLayout-case2-cs", TestSubcase::Create<BasicStdLayoutCase2CS>));
9103 	addChild(new TestSubcase(m_context, "basic-stdLayout-case3-vs", TestSubcase::Create<BasicStdLayoutCase3VS>));
9104 	addChild(new TestSubcase(m_context, "basic-stdLayout-case3-cs", TestSubcase::Create<BasicStdLayoutCase3CS>));
9105 	addChild(new TestSubcase(m_context, "basic-stdLayout-case4-vs", TestSubcase::Create<BasicStdLayoutCase4VS>));
9106 	addChild(new TestSubcase(m_context, "basic-stdLayout-case4-cs", TestSubcase::Create<BasicStdLayoutCase4CS>));
9107 	addChild(new TestSubcase(m_context, "basic-operations-case1-vs", TestSubcase::Create<BasicOperationsCase1VS>));
9108 	addChild(new TestSubcase(m_context, "basic-operations-case1-cs", TestSubcase::Create<BasicOperationsCase1CS>));
9109 	addChild(new TestSubcase(m_context, "basic-operations-case2-vs", TestSubcase::Create<BasicOperationsCase2VS>));
9110 	addChild(new TestSubcase(m_context, "basic-operations-case2-cs", TestSubcase::Create<BasicOperationsCase2CS>));
9111 	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-vs",
9112 							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1VS>));
9113 	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case1-cs",
9114 							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase1CS>));
9115 	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-vs",
9116 							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2VS>));
9117 	addChild(new TestSubcase(m_context, "basic-stdLayout_UBO_SSBO-case2-cs",
9118 							 TestSubcase::Create<Basic_UBO_SSBO_LayoutCase2CS>));
9119 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-vs",
9120 							 TestSubcase::Create<BasicMatrixOperationsCase1VS>));
9121 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case1-cs",
9122 							 TestSubcase::Create<BasicMatrixOperationsCase1CS>));
9123 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-vs",
9124 							 TestSubcase::Create<BasicMatrixOperationsCase2VS>));
9125 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case2-cs",
9126 							 TestSubcase::Create<BasicMatrixOperationsCase2CS>));
9127 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-vs",
9128 							 TestSubcase::Create<BasicMatrixOperationsCase3VS>));
9129 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case3-cs",
9130 							 TestSubcase::Create<BasicMatrixOperationsCase3CS>));
9131 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-vs",
9132 							 TestSubcase::Create<BasicMatrixOperationsCase4VS>));
9133 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case4-cs",
9134 							 TestSubcase::Create<BasicMatrixOperationsCase4CS>));
9135 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-vs",
9136 							 TestSubcase::Create<BasicMatrixOperationsCase5VS>));
9137 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case5-cs",
9138 							 TestSubcase::Create<BasicMatrixOperationsCase5CS>));
9139 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-vs",
9140 							 TestSubcase::Create<BasicMatrixOperationsCase6VS>));
9141 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case6-cs",
9142 							 TestSubcase::Create<BasicMatrixOperationsCase6CS>));
9143 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-vs",
9144 							 TestSubcase::Create<BasicMatrixOperationsCase7VS>));
9145 	addChild(new TestSubcase(m_context, "basic-matrixOperations-case7-cs",
9146 							 TestSubcase::Create<BasicMatrixOperationsCase7CS>));
9147 	addChild(new TestSubcase(m_context, "basic-noBindingLayout", TestSubcase::Create<BasicNoBindingLayout>));
9148 	addChild(new TestSubcase(m_context, "basic-readonly-writeonly", TestSubcase::Create<BasicReadonlyWriteonly>));
9149 	addChild(new TestSubcase(m_context, "basic-name-match", TestSubcase::Create<BasicNameMatch>));
9150 	addChild(new TestSubcase(m_context, "advanced-switchBuffers", TestSubcase::Create<AdvancedSwitchBuffers>));
9151 	addChild(new TestSubcase(m_context, "advanced-switchBuffers-cs", TestSubcase::Create<AdvancedSwitchBuffersCS>));
9152 	addChild(new TestSubcase(m_context, "advanced-switchPrograms", TestSubcase::Create<AdvancedSwitchPrograms>));
9153 	addChild(new TestSubcase(m_context, "advanced-switchPrograms-cs", TestSubcase::Create<AdvancedSwitchProgramsCS>));
9154 	addChild(new TestSubcase(m_context, "advanced-write-fragment", TestSubcase::Create<AdvancedWriteFragment>));
9155 	addChild(new TestSubcase(m_context, "advanced-write-geometry", TestSubcase::Create<AdvancedWriteGeometry>));
9156 	addChild(new TestSubcase(m_context, "advanced-write-tessellation", TestSubcase::Create<AdvancedWriteTessellation>));
9157 	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1",
9158 							 TestSubcase::Create<AdvancedIndirectAddressingCase1>));
9159 	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case1-cs",
9160 							 TestSubcase::Create<AdvancedIndirectAddressingCase1CS>));
9161 	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2",
9162 							 TestSubcase::Create<AdvancedIndirectAddressingCase2>));
9163 	addChild(new TestSubcase(m_context, "advanced-indirectAddressing-case2-cs",
9164 							 TestSubcase::Create<AdvancedIndirectAddressingCase2CS>));
9165 	addChild(new TestSubcase(m_context, "advanced-readWrite-case1", TestSubcase::Create<AdvancedReadWriteCase1>));
9166 	addChild(new TestSubcase(m_context, "advanced-readWrite-case1-cs", TestSubcase::Create<AdvancedReadWriteCase1CS>));
9167 	addChild(new TestSubcase(m_context, "advanced-usage-case1", TestSubcase::Create<AdvancedUsageCase1>));
9168 	addChild(new TestSubcase(m_context, "advanced-usage-sync", TestSubcase::Create<AdvancedUsageSync>));
9169 	addChild(new TestSubcase(m_context, "advanced-usage-sync-cs", TestSubcase::Create<AdvancedUsageSyncCS>));
9170 	addChild(new TestSubcase(m_context, "advanced-usage-operators", TestSubcase::Create<AdvancedUsageOperators>));
9171 	addChild(new TestSubcase(m_context, "advanced-usage-operators-cs", TestSubcase::Create<AdvancedUsageOperatorsCS>));
9172 	addChild(
9173 		new TestSubcase(m_context, "advanced-unsizedArrayLength", TestSubcase::Create<AdvancedUnsizedArrayLength>));
9174 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec",
9175 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec>));
9176 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC",
9177 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC>));
9178 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matR",
9179 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matR>));
9180 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct",
9181 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct>));
9182 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-vec",
9183 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_vec>));
9184 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matC",
9185 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matC>));
9186 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR",
9187 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR>));
9188 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-struct",
9189 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_struct>));
9190 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-vec",
9191 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_vec>));
9192 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-packed-matC",
9193 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_packed_matC>));
9194 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-shared-matR",
9195 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_shared_matR>));
9196 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-vec",
9197 							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_vec>));
9198 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std430-matC-pad",
9199 							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std430_matC_pad>));
9200 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-matR",
9201 							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_matR>));
9202 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-fs-std140-struct",
9203 							 TestSubcase::Create<AdvancedUnsizedArrayLength_fs_std140_struct>));
9204 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std430-vec",
9205 							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std430_vec_pad>));
9206 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-matC",
9207 							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_matC>));
9208 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-packed-matR",
9209 							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_packed_matR>));
9210 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-vs-std140-struct",
9211 							 TestSubcase::Create<AdvancedUnsizedArrayLength_vs_std140_struct>));
9212 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-pad",
9213 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_pad>));
9214 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-matC-pad",
9215 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_matC_pad>));
9216 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std140-matR-pad",
9217 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std140_matR_pad>));
9218 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-struct-pad",
9219 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_struct_pad>));
9220 
9221 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeOffset",
9222 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_offset>));
9223 
9224 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindrangeSize",
9225 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_size>));
9226 
9227 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-bindbaseAfter",
9228 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_after>));
9229 
9230 	addChild(new TestSubcase(m_context, "advanced-unsizedArrayLength-cs-std430-vec-indexing",
9231 							 TestSubcase::Create<AdvancedUnsizedArrayLength_cs_std430_vec_indexing>));
9232 
9233 	addChild(new TestSubcase(m_context, "advanced-matrix", TestSubcase::Create<AdvancedMatrix>));
9234 	addChild(new TestSubcase(m_context, "advanced-matrix-cs", TestSubcase::Create<AdvancedMatrixCS>));
9235 	addChild(new TestSubcase(m_context, "negative-api-bind", TestSubcase::Create<NegativeAPIBind>));
9236 	addChild(new TestSubcase(m_context, "negative-api-blockBinding", TestSubcase::Create<NegativeAPIBlockBinding>));
9237 	addChild(new TestSubcase(m_context, "negative-glsl-compileTime", TestSubcase::Create<NegativeGLSLCompileTime>));
9238 	addChild(new TestSubcase(m_context, "negative-glsl-linkTime", TestSubcase::Create<NegativeGLSLLinkTime>));
9239 }
9240 
9241 } // namespace gl4cts
9242