• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "gl4cES31CompatibilityTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "glwEnums.hpp"
27 #include "tcuMatrix.hpp"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include <assert.h>
31 #include <cstdarg>
32 #include <map>
33 
34 namespace gl4cts
35 {
36 namespace es31compatibility
37 {
38 using namespace glw;
39 namespace
40 {
41 typedef tcu::Vec2  vec2;
42 typedef tcu::Vec4  vec4;
43 typedef tcu::IVec4 ivec4;
44 typedef tcu::UVec4 uvec4;
45 typedef tcu::Mat4  mat4;
46 
47 enum Target
48 {
49 	T2D = 0,
50 	T3D,
51 	TCM,
52 	T2DA
53 };
54 
55 const char* const kGLSLVer = "#version 310 es";
56 const char* const kGLSLSIA = NL "#extension GL_OES_shader_image_atomic : require";
57 const char* const kGLSLPrec =
58 	NL "precision highp float;" NL "precision highp int;" NL "precision highp sampler2D;" NL
59 	   "precision highp sampler3D;" NL "precision highp samplerCube;" NL "precision highp sampler2DArray;" NL
60 	   "precision highp isampler2D;" NL "precision highp isampler3D;" NL "precision highp isamplerCube;" NL
61 	   "precision highp isampler2DArray;" NL "precision highp usampler2D;" NL "precision highp usampler3D;" NL
62 	   "precision highp usamplerCube;" NL "precision highp usampler2DArray;" NL "precision highp image2D;" NL
63 	   "precision highp image3D;" NL "precision highp imageCube;" NL "precision highp image2DArray;" NL
64 	   "precision highp iimage2D;" NL "precision highp iimage3D;" NL "precision highp iimageCube;" NL
65 	   "precision highp iimage2DArray;" NL "precision highp uimage2D;" NL "precision highp uimage3D;" NL
66 	   "precision highp uimageCube;" NL "precision highp uimage2DArray;";
67 
68 class ShaderImageLoadStoreBase : public deqp::SubcaseBase
69 {
70 public:
Title()71 	virtual std::string Title()
72 	{
73 		return "";
74 	}
75 
Purpose()76 	virtual std::string Purpose()
77 	{
78 		return "";
79 	}
80 
Method()81 	virtual std::string Method()
82 	{
83 		return "";
84 	}
85 
PassCriteria()86 	virtual std::string PassCriteria()
87 	{
88 		return "";
89 	}
90 
IsVSFSAvailable(int requiredVS,int requiredFS)91 	bool IsVSFSAvailable(int requiredVS, int requiredFS)
92 	{
93 		GLint imagesVS, imagesFS;
94 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
95 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &imagesFS);
96 		if (imagesVS >= requiredVS && imagesFS >= requiredFS)
97 			return true;
98 		else
99 		{
100 			std::ostringstream reason;
101 			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
102 				   << std::endl
103 				   << "Required " << requiredFS << " FS image uniforms but only " << imagesFS << " available."
104 				   << std::endl;
105 			OutputNotSupported(reason.str());
106 			return false;
107 		}
108 	}
IsSSBInVSFSAvailable(int required)109 	bool IsSSBInVSFSAvailable(int required)
110 	{
111 		GLint blocksVS, blocksFS;
112 		glGetIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &blocksVS);
113 		glGetIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &blocksFS);
114 		if (blocksVS >= required && blocksFS >= required)
115 			return true;
116 		else
117 		{
118 			std::ostringstream reason;
119 			reason << "Required " << required << " VS storage blocks but only " << blocksVS << " available."
120 				   << std::endl
121 				   << "Required " << required << " FS storage blocks but only " << blocksFS << " available."
122 				   << std::endl;
123 			OutputNotSupported(reason.str());
124 			return false;
125 		}
126 	}
127 
IsImageAtomicSupported()128 	bool IsImageAtomicSupported()
129 	{
130 		bool is_at_least_gl_45 =
131 			(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
132 		bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility");
133 		if (!(is_at_least_gl_45 || is_arb_es31_compatibility))
134 		{
135 			std::ostringstream reason;
136 			reason << "Required GL_OES_shader_image_atomic is not available." << std::endl;
137 			OutputNotSupported(reason.str());
138 			return false;
139 		}
140 		return true;
141 	}
142 
AreOutputsAvailable(int required)143 	bool AreOutputsAvailable(int required)
144 	{
145 		GLint outputs;
146 		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &outputs);
147 		if (outputs < required)
148 		{
149 			std::ostringstream reason;
150 			reason << "Required " << required << " shader output resources but only " << outputs << " available."
151 				   << std::endl;
152 			OutputNotSupported(reason.str());
153 			return false;
154 		}
155 		return true;
156 	}
157 
getWindowWidth()158 	int getWindowWidth()
159 	{
160 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
161 		return renderTarget.getWidth();
162 	}
163 
getWindowHeight()164 	int getWindowHeight()
165 	{
166 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
167 		return renderTarget.getHeight();
168 	}
169 
ColorEqual(const vec4 & c0,const vec4 & c1,const vec4 & epsilon)170 	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
171 	{
172 		if (fabs(c0[0] - c1[0]) > epsilon[0])
173 			return false;
174 		if (fabs(c0[1] - c1[1]) > epsilon[1])
175 			return false;
176 		if (fabs(c0[2] - c1[2]) > epsilon[2])
177 			return false;
178 		if (fabs(c0[3] - c1[3]) > epsilon[3])
179 			return false;
180 		return true;
181 	}
182 
Equal(const vec4 & v0,const vec4 & v1,GLenum internalformat)183 	bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
184 	{
185 		if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RGBA8)
186 		{
187 			return ColorEqual(v0, v1, vec4(0.01f));
188 		}
189 		return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
190 	}
Equal(const ivec4 & a,const ivec4 & b,GLenum)191 	bool Equal(const ivec4& a, const ivec4& b, GLenum)
192 	{
193 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
194 	}
Equal(const uvec4 & a,const uvec4 & b,GLenum)195 	bool Equal(const uvec4& a, const uvec4& b, GLenum)
196 	{
197 		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
198 	}
199 
200 	template <class T>
ToString(T v)201 	std::string ToString(T v)
202 	{
203 		std::ostringstream s;
204 		s << "[";
205 		for (int i = 0; i < 4; ++i)
206 			s << v[i] << (i == 3 ? "" : ",");
207 		s << "]";
208 		return s.str();
209 	}
210 
211 	template <typename T>
CompareValues(T * map_data,int kSize,const T & expected_value,GLenum internalformat=0,int layers=1)212 	bool CompareValues(T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0, int layers = 1)
213 	{
214 		for (int i = 0; i < kSize * kSize * layers; ++i)
215 		{
216 			if (!Equal(map_data[i], expected_value, internalformat))
217 			{
218 				m_context.getTestContext().getLog()
219 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
220 					<< ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage;
221 				return false;
222 			}
223 		}
224 		return true;
225 	}
226 	template <typename T>
CompareValues(bool always,T * map_data,int kSize,const T & expected_value,GLenum internalformat=0,int layers=1)227 	bool CompareValues(bool always, T* map_data, int kSize, const T& expected_value, GLenum internalformat = 0,
228 					   int layers = 1)
229 	{
230 		(void)internalformat;
231 		for (int i = 0; i < kSize * kSize * layers; ++i)
232 		{
233 			if (always)
234 			{
235 				m_context.getTestContext().getLog()
236 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
237 					<< ". Value should be: " << ToString(expected_value).c_str() << "." << tcu::TestLog::EndMessage;
238 			}
239 		}
240 		return true;
241 	}
242 
CheckFB(vec4 expected)243 	bool CheckFB(vec4 expected)
244 	{
245 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
246 		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
247 		vec4 g_color_eps = vec4(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
248 								1.f / (float)(1 << pixelFormat.blueBits), 1.f);
249 		vec4				 g_color_max = vec4(255);
250 		std::vector<GLubyte> fb(getWindowWidth() * getWindowHeight() * 4);
251 		int					 fb_w = getWindowWidth();
252 		int					 fb_h = getWindowHeight();
253 		glReadPixels(0, 0, fb_w, fb_h, GL_RGBA, GL_UNSIGNED_BYTE, &fb[0]);
254 		for (GLint i = 0, y = 0; y < fb_h; ++y)
255 			for (GLint x = 0; x < fb_w; ++x, i += 4)
256 			{
257 				if (fabs(fb[i + 0] / g_color_max[0] - expected[0]) > g_color_eps[0] ||
258 					fabs(fb[i + 1] / g_color_max[1] - expected[1]) > g_color_eps[1] ||
259 					fabs(fb[i + 2] / g_color_max[2] - expected[2]) > g_color_eps[2])
260 				{
261 					m_context.getTestContext().getLog()
262 						<< tcu::TestLog::Message << "Incorrect framebuffer color at pixel (" << x << ", " << y
263 						<< "). Color is (" << fb[i + 0] / g_color_max[0] << ", " << fb[i + 1] / g_color_max[1] << ", "
264 						<< fb[i + 2] / g_color_max[2] << "). Color should be (" << expected[0] << ", " << expected[1]
265 						<< ", " << expected[2] << ")." << tcu::TestLog::EndMessage;
266 					return false;
267 				}
268 			}
269 		return true;
270 	}
271 
CompileShader(GLuint shader)272 	bool CompileShader(GLuint shader)
273 	{
274 		glCompileShader(shader);
275 
276 		GLint status;
277 		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
278 		if (status == GL_FALSE)
279 		{
280 			GLsizei length;
281 			GLchar  log[1024];
282 			glGetShaderInfoLog(shader, sizeof(log), &length, log);
283 			if (length > 1)
284 			{
285 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
286 													<< log << tcu::TestLog::EndMessage;
287 			}
288 			return false;
289 		}
290 		return true;
291 	}
292 
LinkProgram(GLuint program)293 	bool LinkProgram(GLuint program)
294 	{
295 		glLinkProgram(program);
296 
297 		GLint status;
298 		glGetProgramiv(program, GL_LINK_STATUS, &status);
299 		if (status == GL_FALSE)
300 		{
301 			GLsizei length;
302 			GLchar  log[1024];
303 			glGetProgramInfoLog(program, sizeof(log), &length, log);
304 			if (length > 1)
305 			{
306 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
307 													<< log << tcu::TestLog::EndMessage;
308 			}
309 			return false;
310 		}
311 		return true;
312 	}
313 
BuildProgram(const char * src_vs,const char * src_fs,bool SIAvs=false,bool SIAfs=false)314 	GLuint BuildProgram(const char* src_vs, const char* src_fs, bool SIAvs = false, bool SIAfs = false)
315 	{
316 		std::ostringstream osvs, osfs;
317 		osvs << kGLSLVer << (SIAvs ? kGLSLSIA : "\n") << kGLSLPrec;
318 		osfs << kGLSLVer << (SIAfs ? kGLSLSIA : "\n") << kGLSLPrec;
319 		std::string hvs = osvs.str();
320 		std::string hfs = osfs.str();
321 
322 		const GLuint p = glCreateProgram();
323 
324 		if (src_vs)
325 		{
326 			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
327 			glAttachShader(p, sh);
328 			glDeleteShader(sh);
329 			const char* const src[2] = { hvs.c_str(), src_vs };
330 			glShaderSource(sh, 2, src, NULL);
331 			if (!CompileShader(sh))
332 			{
333 				m_context.getTestContext().getLog()
334 					<< tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
335 				return p;
336 			}
337 		}
338 		if (src_fs)
339 		{
340 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
341 			glAttachShader(p, sh);
342 			glDeleteShader(sh);
343 			const char* const src[2] = { hfs.c_str(), src_fs };
344 			glShaderSource(sh, 2, src, NULL);
345 			if (!CompileShader(sh))
346 			{
347 				m_context.getTestContext().getLog()
348 					<< tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
349 				return p;
350 			}
351 		}
352 		if (!LinkProgram(p))
353 		{
354 			if (src_vs)
355 				m_context.getTestContext().getLog()
356 					<< tcu::TestLog::Message << hvs.c_str() << src_vs << tcu::TestLog::EndMessage;
357 			if (src_fs)
358 				m_context.getTestContext().getLog()
359 					<< tcu::TestLog::Message << hfs.c_str() << src_fs << tcu::TestLog::EndMessage;
360 			return p;
361 		}
362 
363 		return p;
364 	}
365 
CreateComputeProgram(const std::string & cs,bool SIA=false)366 	GLuint CreateComputeProgram(const std::string& cs, bool SIA = false)
367 	{
368 		std::ostringstream oscs;
369 		oscs << kGLSLVer << (SIA ? kGLSLSIA : "\n") << kGLSLPrec;
370 		std::string  hcs = oscs.str();
371 		const GLuint p   = glCreateProgram();
372 
373 		if (!cs.empty())
374 		{
375 			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
376 			glAttachShader(p, sh);
377 			glDeleteShader(sh);
378 			const char* const src[2] = { hcs.c_str(), cs.c_str() };
379 			glShaderSource(sh, 2, src, NULL);
380 			if (!CompileShader(sh))
381 			{
382 				m_context.getTestContext().getLog()
383 					<< tcu::TestLog::Message << src[0] << src[1] << tcu::TestLog::EndMessage;
384 				return p;
385 			}
386 		}
387 		if (!LinkProgram(p))
388 		{
389 			if (!cs.empty())
390 				m_context.getTestContext().getLog()
391 					<< tcu::TestLog::Message << hcs.c_str() << cs.c_str() << tcu::TestLog::EndMessage;
392 			return p;
393 		}
394 
395 		return p;
396 	}
397 
BuildShaderProgram(GLenum type,const char * src)398 	GLuint BuildShaderProgram(GLenum type, const char* src)
399 	{
400 		const char* const src3[3] = { kGLSLVer, kGLSLPrec, src };
401 		const GLuint	  p		  = glCreateShaderProgramv(type, 3, src3);
402 		GLint			  status;
403 		glGetProgramiv(p, GL_LINK_STATUS, &status);
404 		if (status == GL_FALSE)
405 		{
406 			GLchar log[1024];
407 			glGetProgramInfoLog(p, sizeof(log), NULL, log);
408 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
409 												<< log << "\n"
410 												<< src3[0] << "\n"
411 												<< src3[1] << "\n"
412 												<< src3[2] << tcu::TestLog::EndMessage;
413 		}
414 		return p;
415 	}
416 
CreateFullViewportQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)417 	void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
418 	{
419 		assert(vao && vbo);
420 
421 		// interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
422 		const float v[] = {
423 			-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,  1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
424 			0.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f,
425 			1.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f,  0.0f,
426 		};
427 		glGenBuffers(1, vbo);
428 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
429 		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
430 		glBindBuffer(GL_ARRAY_BUFFER, 0);
431 
432 		if (ebo)
433 		{
434 			std::vector<GLushort> index_data(4);
435 			for (int i = 0; i < 4; ++i)
436 			{
437 				index_data[i] = static_cast<GLushort>(i);
438 			}
439 			glGenBuffers(1, ebo);
440 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
441 			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
442 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
443 		}
444 
445 		glGenVertexArrays(1, vao);
446 		glBindVertexArray(*vao);
447 		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
448 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
449 
450 		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
451 
452 		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11,
453 
454 							  reinterpret_cast<void*>(sizeof(float) * 5));
455 
456 		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
457 
458 		glBindBuffer(GL_ARRAY_BUFFER, 0);
459 		glEnableVertexAttribArray(0);
460 		glEnableVertexAttribArray(1);
461 		glEnableVertexAttribArray(2);
462 		glEnableVertexAttribArray(3);
463 		if (ebo)
464 		{
465 			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
466 		}
467 		glBindVertexArray(0);
468 	}
469 
FormatEnumToString(GLenum e)470 	std::string FormatEnumToString(GLenum e)
471 	{
472 		switch (e)
473 		{
474 		case GL_RGBA32F:
475 			return "rgba32f";
476 		case GL_RGBA16F:
477 			return "rgba16f";
478 		case GL_R32F:
479 			return "r32f";
480 
481 		case GL_RGBA32UI:
482 			return "rgba32ui";
483 		case GL_RGBA16UI:
484 			return "rgba16ui";
485 		case GL_RGBA8UI:
486 			return "rgba8ui";
487 		case GL_R32UI:
488 			return "r32ui";
489 
490 		case GL_RGBA32I:
491 			return "rgba32i";
492 		case GL_RGBA16I:
493 			return "rgba16i";
494 		case GL_RGBA8I:
495 			return "rgba8i";
496 		case GL_R32I:
497 			return "r32i";
498 
499 		case GL_RGBA8:
500 			return "rgba8";
501 
502 		case GL_RGBA8_SNORM:
503 			return "rgba8_snorm";
504 		}
505 
506 		assert(0);
507 		return "";
508 	}
509 
510 	template <typename T>
511 	GLenum Format();
512 
513 	template <typename T>
514 	GLenum Type();
515 
516 	template <typename T>
517 	std::string TypePrefix();
518 
519 	template <typename T>
520 	GLenum ImageType(GLenum target);
521 
ClearBuffer(GLenum buffer,GLint drawbuffer,const vec4 & color)522 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
523 	{
524 		glClearBufferfv(buffer, drawbuffer, &color[0]);
525 	}
526 
ClearBuffer(GLenum buffer,GLint drawbuffer,const ivec4 & color)527 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
528 	{
529 		glClearBufferiv(buffer, drawbuffer, &color[0]);
530 	}
531 
ClearBuffer(GLenum buffer,GLint drawbuffer,const uvec4 & color)532 	void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
533 	{
534 		glClearBufferuiv(buffer, drawbuffer, &color[0]);
535 	}
536 
CheckMax(GLenum pname,GLint min_value)537 	bool CheckMax(GLenum pname, GLint min_value)
538 	{
539 		GLboolean b;
540 		GLint	 i;
541 		GLfloat   f;
542 		GLint64   i64;
543 
544 		glGetIntegerv(pname, &i);
545 		if (i < min_value)
546 			return false;
547 
548 		glGetBooleanv(pname, &b);
549 		if (b != (i ? GL_TRUE : GL_FALSE))
550 			return false;
551 
552 		glGetFloatv(pname, &f);
553 		if (static_cast<GLint>(f) < min_value)
554 			return false;
555 
556 		glGetInteger64v(pname, &i64);
557 		if (static_cast<GLint>(i64) < min_value)
558 			return false;
559 
560 		return true;
561 	}
562 
CheckBinding(GLuint unit,GLuint texture,GLint level,GLboolean layered,GLint layer,GLenum access,GLenum format)563 	bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
564 					  GLenum format)
565 	{
566 		GLint	 i;
567 		GLboolean b;
568 
569 		glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
570 		if (static_cast<GLuint>(i) != texture)
571 		{
572 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
573 												<< " should be " << texture << "." << tcu::TestLog::EndMessage;
574 			return false;
575 		}
576 
577 		glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
578 		if (i != level)
579 		{
580 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
581 												<< " should be " << level << "." << tcu::TestLog::EndMessage;
582 			return false;
583 		}
584 
585 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
586 		glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
587 		if (i != layered || b != layered)
588 		{
589 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
590 												<< " should be " << layered << "." << tcu::TestLog::EndMessage;
591 			return false;
592 		}
593 
594 		glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
595 		if (i != layer)
596 		{
597 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
598 												<< " should be " << layer << "." << tcu::TestLog::EndMessage;
599 			return false;
600 		}
601 
602 		glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
603 		if (static_cast<GLenum>(i) != access)
604 		{
605 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
606 												<< " should be " << access << "." << tcu::TestLog::EndMessage;
607 			return false;
608 		}
609 
610 		glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
611 		if (static_cast<GLenum>(i) != format)
612 		{
613 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
614 												<< " should be " << format << "." << tcu::TestLog::EndMessage;
615 			return false;
616 		}
617 
618 		return true;
619 	}
EnumToString(GLenum e)620 	const char* EnumToString(GLenum e)
621 	{
622 		switch (e)
623 		{
624 		case GL_TEXTURE_2D:
625 			return "GL_TEXTURE_2D";
626 		case GL_TEXTURE_3D:
627 			return "GL_TEXTURE_3D";
628 		case GL_TEXTURE_CUBE_MAP:
629 			return "GL_TEXTURE_CUBE_MAP";
630 		case GL_TEXTURE_2D_ARRAY:
631 			return "GL_TEXTURE_2D_ARRAY";
632 
633 		default:
634 			assert(0);
635 			break;
636 		}
637 		return NULL;
638 	}
639 };
640 
641 template <>
Format()642 GLenum ShaderImageLoadStoreBase::Format<vec4>()
643 {
644 	return GL_RGBA;
645 }
646 
647 template <>
Format()648 GLenum ShaderImageLoadStoreBase::Format<ivec4>()
649 {
650 	return GL_RGBA_INTEGER;
651 }
652 
653 template <>
Format()654 GLenum ShaderImageLoadStoreBase::Format<uvec4>()
655 {
656 	return GL_RGBA_INTEGER;
657 }
658 
659 template <>
Format()660 GLenum ShaderImageLoadStoreBase::Format<GLint>()
661 {
662 	return GL_RED_INTEGER;
663 }
664 
665 template <>
Format()666 GLenum ShaderImageLoadStoreBase::Format<GLuint>()
667 {
668 	return GL_RED_INTEGER;
669 }
670 
671 template <>
Type()672 GLenum ShaderImageLoadStoreBase::Type<vec4>()
673 {
674 	return GL_FLOAT;
675 }
676 
677 template <>
Type()678 GLenum ShaderImageLoadStoreBase::Type<ivec4>()
679 {
680 	return GL_INT;
681 }
682 
683 template <>
Type()684 GLenum ShaderImageLoadStoreBase::Type<uvec4>()
685 {
686 	return GL_UNSIGNED_INT;
687 }
688 
689 template <>
Type()690 GLenum ShaderImageLoadStoreBase::Type<GLint>()
691 {
692 	return GL_INT;
693 }
694 
695 template <>
Type()696 GLenum ShaderImageLoadStoreBase::Type<GLuint>()
697 {
698 	return GL_UNSIGNED_INT;
699 }
700 
701 template <>
TypePrefix()702 std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
703 {
704 	return "";
705 }
706 
707 template <>
708 
TypePrefix()709 std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
710 {
711 	return "i";
712 }
713 
714 template <>
TypePrefix()715 std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
716 {
717 	return "u";
718 }
719 
720 template <>
721 
TypePrefix()722 std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
723 {
724 	return "i";
725 }
726 
727 template <>
TypePrefix()728 std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
729 {
730 	return "u";
731 }
732 
733 template <>
ImageType(GLenum target)734 GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
735 {
736 	switch (target)
737 	{
738 	case GL_TEXTURE_2D:
739 		return GL_IMAGE_2D;
740 	case GL_TEXTURE_3D:
741 		return GL_IMAGE_3D;
742 	case GL_TEXTURE_CUBE_MAP:
743 		return GL_IMAGE_CUBE;
744 	case GL_TEXTURE_2D_ARRAY:
745 		return GL_IMAGE_2D_ARRAY;
746 	}
747 	assert(0);
748 	return 0;
749 }
750 
751 template <>
ImageType(GLenum target)752 GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
753 {
754 	switch (target)
755 	{
756 	case GL_TEXTURE_2D:
757 		return GL_INT_IMAGE_2D;
758 	case GL_TEXTURE_3D:
759 		return GL_INT_IMAGE_3D;
760 	case GL_TEXTURE_CUBE_MAP:
761 		return GL_INT_IMAGE_CUBE;
762 	case GL_TEXTURE_2D_ARRAY:
763 		return GL_INT_IMAGE_2D_ARRAY;
764 	}
765 	assert(0);
766 	return 0;
767 }
768 
769 template <>
ImageType(GLenum target)770 GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
771 {
772 	switch (target)
773 	{
774 	case GL_TEXTURE_2D:
775 		return GL_UNSIGNED_INT_IMAGE_2D;
776 	case GL_TEXTURE_3D:
777 		return GL_UNSIGNED_INT_IMAGE_3D;
778 	case GL_TEXTURE_CUBE_MAP:
779 		return GL_UNSIGNED_INT_IMAGE_CUBE;
780 	case GL_TEXTURE_2D_ARRAY:
781 		return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
782 	}
783 	assert(0);
784 	return 0;
785 }
786 
Components(GLenum e)787 int Components(GLenum e)
788 {
789 	return (e == GL_RED || e == GL_RED_INTEGER) ? 1 : 4;
790 }
791 
Shorts(GLenum e)792 bool Shorts(GLenum e)
793 {
794 	return (e == GL_RGBA16I || e == GL_RGBA16UI);
795 }
796 
Bytes(GLenum e)797 bool Bytes(GLenum e)
798 {
799 	return (e == GL_RGBA8I || e == GL_RGBA8UI || e == GL_RGBA8 || e == GL_RGBA8_SNORM);
800 }
801 
802 template <typename T>
803 class ShortByteData
804 {
805 public:
806 	std::vector<T>		 data;
807 	std::vector<GLshort> datas;
808 	std::vector<GLbyte>  datab;
809 
ShortByteData(int size,const T & value,GLenum internalformat,GLenum format)810 	ShortByteData(int size, const T& value, GLenum internalformat, GLenum format)
811 		: data(size * size, value), datas(size * size * 4), datab(size * size * 4)
812 	{
813 		if (Components(format) == 1)
814 			for (unsigned i = 0; i < data.size() / 4; ++i)
815 			{
816 				data[i][0] = data[i * 4][0];
817 				data[i][1] = data[i * 4 + 1][0];
818 				data[i][2] = data[i * 4 + 2][0];
819 				data[i][3] = data[i * 4 + 3][0];
820 			}
821 		if (Shorts(internalformat))
822 		{
823 			for (unsigned i = 0; i < datas.size(); i += 4)
824 			{
825 				datas[i]	 = static_cast<GLshort>(data[i / 4][0]);
826 				datas[i + 1] = static_cast<GLshort>(data[i / 4][1]);
827 				datas[i + 2] = static_cast<GLshort>(data[i / 4][2]);
828 				datas[i + 3] = static_cast<GLshort>(data[i / 4][3]);
829 			}
830 		}
831 		if (Bytes(internalformat))
832 		{
833 			for (unsigned i = 0; i < datas.size(); i += 4)
834 			{
835 				if (internalformat == GL_RGBA8I || internalformat == GL_RGBA8UI)
836 				{
837 					datab[i]	 = static_cast<GLbyte>(data[i / 4][0]);
838 					datab[i + 1] = static_cast<GLbyte>(data[i / 4][1]);
839 					datab[i + 2] = static_cast<GLbyte>(data[i / 4][2]);
840 					datab[i + 3] = static_cast<GLbyte>(data[i / 4][3]);
841 				}
842 				else if (internalformat == GL_RGBA8)
843 				{
844 					datab[i]	 = static_cast<GLbyte>(data[i / 4][0] * 255);
845 					datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 255);
846 					datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 255);
847 					datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 255);
848 				}
849 				else
850 				{ // GL_RGBA8_SNORM
851 					datab[i]	 = static_cast<GLbyte>(data[i / 4][0] * 127);
852 					datab[i + 1] = static_cast<GLbyte>(data[i / 4][1] * 127);
853 					datab[i + 2] = static_cast<GLbyte>(data[i / 4][2] * 127);
854 					datab[i + 3] = static_cast<GLbyte>(data[i / 4][3] * 127);
855 				}
856 			}
857 		}
858 	}
859 };
860 
861 //-----------------------------------------------------------------------------
862 // 1.1.1 BasicAPIGet
863 //-----------------------------------------------------------------------------
864 class BasicAPIGet : public ShaderImageLoadStoreBase
865 {
Run()866 	virtual long Run()
867 	{
868 		if (!CheckMax(GL_MAX_IMAGE_UNITS, 4))
869 		{
870 			m_context.getTestContext().getLog()
871 				<< tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
872 			return ERROR;
873 		}
874 		if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 4))
875 		{
876 			m_context.getTestContext().getLog()
877 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
878 				<< tcu::TestLog::EndMessage;
879 			return ERROR;
880 		}
881 		if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
882 		{
883 			m_context.getTestContext().getLog()
884 				<< tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
885 				<< tcu::TestLog::EndMessage;
886 			return ERROR;
887 		}
888 		if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 0))
889 		{
890 			m_context.getTestContext().getLog()
891 				<< tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
892 				<< tcu::TestLog::EndMessage;
893 			return ERROR;
894 		}
895 		if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 4))
896 		{
897 			m_context.getTestContext().getLog()
898 				<< tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
899 				<< tcu::TestLog::EndMessage;
900 			return ERROR;
901 		}
902 		if (!CheckMax(GL_MAX_COMPUTE_IMAGE_UNIFORMS, 4))
903 		{
904 			m_context.getTestContext().getLog()
905 				<< tcu::TestLog::Message << "GL_MAX_COMPUTE_IMAGE_UNIFORMS value is invalid."
906 				<< tcu::TestLog::EndMessage;
907 			return ERROR;
908 		}
909 		return NO_ERROR;
910 	}
911 };
912 
913 //-----------------------------------------------------------------------------
914 // 1.1.2 BasicAPIBind
915 //-----------------------------------------------------------------------------
916 class BasicAPIBind : public ShaderImageLoadStoreBase
917 {
918 	GLuint m_texture;
919 
Setup()920 	virtual long Setup()
921 	{
922 		m_texture = 0;
923 		return NO_ERROR;
924 	}
925 
Run()926 	virtual long Run()
927 	{
928 		bool status = true;
929 		for (GLuint index = 0; index < 4; ++index)
930 		{
931 			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI))
932 			{
933 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
934 													<< " has invalid default state." << tcu::TestLog::EndMessage;
935 				status = false;
936 			}
937 		}
938 
939 		glGenTextures(1, &m_texture);
940 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
941 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 4, GL_RG32F, 16, 16, 4);
942 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
943 
944 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
945 		if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
946 			status = false;
947 
948 		glBindImageTexture(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
949 		if (!CheckBinding(3, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
950 			status = false;
951 
952 		glBindImageTexture(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI);
953 		if (!CheckBinding(1, m_texture, 3, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA8UI))
954 			status = false;
955 
956 		glBindImageTexture(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
957 		if (!CheckBinding(2, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
958 			status = false;
959 
960 		glDeleteTextures(1, &m_texture);
961 		m_texture = 0;
962 
963 		for (GLuint index = 0; index < 4; ++index)
964 		{
965 			GLint name;
966 			glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
967 			if (name != 0)
968 			{
969 				m_context.getTestContext().getLog()
970 					<< tcu::TestLog::Message << "Binding point " << index
971 					<< " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
972 				status = false;
973 			}
974 			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI))
975 				status = false;
976 		}
977 
978 		return status ? NO_ERROR : ERROR;
979 	}
980 
Cleanup()981 	virtual long Cleanup()
982 	{
983 		glDeleteTextures(1, &m_texture);
984 		return NO_ERROR;
985 	}
986 };
987 //-----------------------------------------------------------------------------
988 // 1.1.3 BasicAPIBarrier
989 //-----------------------------------------------------------------------------
990 class BasicAPIBarrier : public ShaderImageLoadStoreBase
991 {
Run()992 	virtual long Run()
993 	{
994 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
995 		glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
996 		glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
997 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
998 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
999 		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1000 		glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1001 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1002 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1003 		glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1004 		glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1005 		glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1006 		glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
1007 
1008 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1009 						GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1010 						GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1011 						GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT |
1012 						GL_SHADER_STORAGE_BARRIER_BIT);
1013 
1014 		glMemoryBarrier(GL_ALL_BARRIER_BITS);
1015 
1016 		return NO_ERROR;
1017 	}
1018 };
1019 
1020 class BasicAPIBarrierByRegion : public ShaderImageLoadStoreBase
1021 {
Run()1022 	virtual long Run()
1023 	{
1024 		glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT);
1025 		glMemoryBarrierByRegion(GL_TEXTURE_FETCH_BARRIER_BIT);
1026 		glMemoryBarrierByRegion(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1027 		glMemoryBarrierByRegion(GL_FRAMEBUFFER_BARRIER_BIT);
1028 		glMemoryBarrierByRegion(GL_ATOMIC_COUNTER_BARRIER_BIT);
1029 		glMemoryBarrierByRegion(GL_SHADER_STORAGE_BARRIER_BIT);
1030 
1031 		glMemoryBarrierByRegion(GL_UNIFORM_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT |
1032 								GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1033 								GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
1034 
1035 		glMemoryBarrierByRegion(GL_ALL_BARRIER_BITS);
1036 		return NO_ERROR;
1037 	}
1038 };
1039 //-----------------------------------------------------------------------------
1040 // 1.1.4 BasicAPITexParam
1041 //-----------------------------------------------------------------------------
1042 class BasicAPITexParam : public ShaderImageLoadStoreBase
1043 {
1044 	GLuint m_texture;
1045 
Setup()1046 	virtual long Setup()
1047 	{
1048 		m_texture = 0;
1049 		return NO_ERROR;
1050 	}
1051 
Run()1052 	virtual long Run()
1053 	{
1054 		glGenTextures(1, &m_texture);
1055 		glBindTexture(GL_TEXTURE_2D, m_texture);
1056 		glTexStorage2D(GL_TEXTURE_2D, 5, GL_RG32F, 16, 16);
1057 
1058 		GLint   i;
1059 		GLfloat f;
1060 
1061 		glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1062 		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1063 		{
1064 			m_context.getTestContext().getLog()
1065 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1066 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1067 				<< tcu::TestLog::EndMessage;
1068 			return ERROR;
1069 		}
1070 		glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1071 		if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1072 		{
1073 			m_context.getTestContext().getLog()
1074 				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1075 				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1076 				<< tcu::TestLog::EndMessage;
1077 			return ERROR;
1078 		}
1079 
1080 		return NO_ERROR;
1081 	}
1082 
Cleanup()1083 	virtual long Cleanup()
1084 	{
1085 		glDeleteTextures(1, &m_texture);
1086 		return NO_ERROR;
1087 	}
1088 };
1089 //-----------------------------------------------------------------------------
1090 // 1.2.1 BasicAllFormatsStore
1091 //-----------------------------------------------------------------------------
1092 class BasicAllFormatsStoreFS : public ShaderImageLoadStoreBase
1093 {
1094 	GLuint m_vao, m_vbo;
1095 
Setup()1096 	virtual long Setup()
1097 	{
1098 		m_vao = 0;
1099 		m_vbo = 0;
1100 		return NO_ERROR;
1101 	}
1102 
Run()1103 	virtual long Run()
1104 	{
1105 		if (!IsVSFSAvailable(0, 1))
1106 			return NOT_SUPPORTED;
1107 
1108 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1109 
1110 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1111 			return ERROR;
1112 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1113 			return ERROR;
1114 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1115 			return ERROR;
1116 
1117 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1118 			return ERROR;
1119 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1120 			return ERROR;
1121 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1122 			return ERROR;
1123 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1124 			return ERROR;
1125 
1126 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1127 			return ERROR;
1128 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1129 			return ERROR;
1130 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1131 			return ERROR;
1132 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1133 			return ERROR;
1134 
1135 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1136 			return ERROR;
1137 
1138 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1139 			return ERROR;
1140 
1141 		return NO_ERROR;
1142 	}
1143 
1144 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)1145 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1146 	{
1147 		const char* src_vs =
1148 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
1149 		GLuint		   program = BuildProgram(src_vs, GenFS(internalformat, write_value).c_str());
1150 		const int	  kSize   = 11;
1151 		std::vector<T> data(kSize * kSize);
1152 		GLuint		   texture;
1153 		glGenTextures(1, &texture);
1154 		glUseProgram(program);
1155 
1156 		GLuint unit = 2;
1157 		glBindTexture(GL_TEXTURE_2D, texture);
1158 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1159 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1160 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1161 		glBindTexture(GL_TEXTURE_2D, 0);
1162 
1163 		glViewport(0, 0, kSize, kSize);
1164 		glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1165 		glBindVertexArray(m_vao);
1166 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1167 
1168 		glBindTexture(GL_TEXTURE_2D, texture);
1169 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1170 
1171 		GLuint		   c_program = CreateComputeProgram(GenC(write_value));
1172 		std::vector<T> out_data(kSize * kSize);
1173 		GLuint		   m_buffer;
1174 		glGenBuffers(1, &m_buffer);
1175 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1176 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1177 
1178 		glUseProgram(c_program);
1179 		glDispatchCompute(1, 1, 1);
1180 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1181 		T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1182 		for (int i = 0; i < kSize * kSize; ++i)
1183 		{
1184 			if (!Equal(map_data[i], expected_value, internalformat))
1185 			{
1186 				m_context.getTestContext().getLog()
1187 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1188 					<< ". Value should be: " << ToString(expected_value).c_str()
1189 					<< ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1190 					<< tcu::TestLog::EndMessage;
1191 				glDeleteTextures(1, &texture);
1192 				glUseProgram(0);
1193 				glDeleteProgram(program);
1194 				glDeleteProgram(c_program);
1195 				glDeleteBuffers(1, &m_buffer);
1196 				return false;
1197 			}
1198 		}
1199 		glDeleteTextures(1, &texture);
1200 		glUseProgram(0);
1201 		glDeleteProgram(program);
1202 		glDeleteProgram(c_program);
1203 		glDeleteBuffers(1, &m_buffer);
1204 		return true;
1205 	}
1206 
Cleanup()1207 	virtual long Cleanup()
1208 	{
1209 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1210 		glDeleteVertexArrays(1, &m_vao);
1211 		glDeleteBuffers(1, &m_vbo);
1212 		return NO_ERROR;
1213 	}
1214 
1215 	template <typename T>
GenFS(GLenum internalformat,const T & value)1216 	std::string GenFS(GLenum internalformat, const T& value)
1217 	{
1218 		std::ostringstream os;
1219 		os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
1220 		   << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1221 								 "  imageStore(g_image, coord, "
1222 		   << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1223 		return os.str();
1224 	}
1225 
1226 	template <typename T>
GenC(const T & value)1227 	std::string GenC(const T& value)
1228 	{
1229 		std::ostringstream os;
1230 		os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1231 		   << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL "  "
1232 		   << TypePrefix<T>()
1233 		   << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1234 			  "  data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1235 			  "  //data[gl_LocalInvocationIndex] = "
1236 		   << value << ";" NL "}";
1237 		return os.str();
1238 	}
1239 };
1240 
1241 class BasicAllFormatsStoreCS : public ShaderImageLoadStoreBase
1242 {
Setup()1243 	virtual long Setup()
1244 	{
1245 		return NO_ERROR;
1246 	}
1247 
1248 	template <typename T>
GenCS(GLenum internalformat,const T & value)1249 	std::string GenCS(GLenum internalformat, const T& value)
1250 	{
1251 		std::ostringstream os;
1252 		os << NL "#define KSIZE 4" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1253 		   << TypePrefix<T>()
1254 		   << "image2D g_image;" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "void main() {" NL
1255 			  "  ivec2 thread_xy = ivec2(gl_LocalInvocationID);" NL "  imageStore(g_image, thread_xy, "
1256 		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1257 		return os.str();
1258 	}
1259 
1260 	template <typename T>
GenC(const T & value)1261 	std::string GenC(const T& value)
1262 	{
1263 		std::ostringstream os;
1264 		os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1265 		   << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL "  "
1266 		   << TypePrefix<T>()
1267 		   << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1268 			  "  data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1269 			  "  //data[gl_LocalInvocationIndex] = "
1270 		   << TypePrefix<T>() << "vec4" << value << ";" NL "}";
1271 		return os.str();
1272 	}
1273 
1274 	template <typename T>
WriteCS(GLenum internalformat,const T & write_value,const T & expected_value)1275 	bool WriteCS(GLenum internalformat, const T& write_value, const T& expected_value)
1276 	{
1277 		const int kSize   = 4;
1278 		GLuint	program = CreateComputeProgram(GenCS(internalformat, write_value));
1279 
1280 		std::vector<T> data(kSize * kSize);
1281 		GLuint		   texture;
1282 		glGenTextures(1, &texture);
1283 
1284 		GLuint unit = 0;
1285 		glBindTexture(GL_TEXTURE_2D, texture);
1286 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1287 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1288 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1289 		glBindTexture(GL_TEXTURE_2D, 0);
1290 		glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1291 		glUseProgram(program);
1292 		glDispatchCompute(1, 1, 1);
1293 
1294 		glBindTexture(GL_TEXTURE_2D, texture);
1295 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1296 
1297 		GLuint		   c_program = CreateComputeProgram(GenC(expected_value));
1298 		std::vector<T> out_data(kSize * kSize);
1299 		GLuint		   m_buffer;
1300 		glGenBuffers(1, &m_buffer);
1301 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1302 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1303 
1304 		glUseProgram(c_program);
1305 		glDispatchCompute(1, 1, 1);
1306 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1307 		T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1308 		for (int i = 0; i < kSize * kSize; ++i)
1309 		{
1310 			if (!Equal(map_data[i], expected_value, internalformat))
1311 			{
1312 				m_context.getTestContext().getLog()
1313 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1314 					<< ". Value should be: " << ToString(expected_value).c_str()
1315 					<< ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1316 					<< tcu::TestLog::EndMessage;
1317 				glDeleteTextures(1, &texture);
1318 				glUseProgram(0);
1319 				glDeleteProgram(program);
1320 				glDeleteProgram(c_program);
1321 				glDeleteBuffers(1, &m_buffer);
1322 				return false;
1323 			}
1324 		}
1325 		glDeleteTextures(1, &texture);
1326 		glUseProgram(0);
1327 		glDeleteProgram(program);
1328 		glDeleteProgram(c_program);
1329 		glDeleteBuffers(1, &m_buffer);
1330 
1331 		return true;
1332 	}
1333 
Run()1334 	virtual long Run()
1335 	{
1336 
1337 		if (!WriteCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1338 			return ERROR;
1339 		if (!WriteCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1340 			return ERROR;
1341 		if (!WriteCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1342 			return ERROR;
1343 
1344 		if (!WriteCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1345 			return ERROR;
1346 		if (!WriteCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1347 			return ERROR;
1348 		if (!WriteCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1349 			return ERROR;
1350 		if (!WriteCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1351 			return ERROR;
1352 
1353 		if (!WriteCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1354 			return ERROR;
1355 		if (!WriteCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1356 			return ERROR;
1357 		if (!WriteCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1358 			return ERROR;
1359 		if (!WriteCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1360 			return ERROR;
1361 
1362 		if (!WriteCS(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1363 			return ERROR;
1364 
1365 		if (!WriteCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1366 			return ERROR;
1367 
1368 		return NO_ERROR;
1369 	}
1370 
Cleanup()1371 	virtual long Cleanup()
1372 	{
1373 		return NO_ERROR;
1374 	}
1375 };
1376 //-----------------------------------------------------------------------------
1377 // 1.2.2 BasicAllFormatsLoad
1378 //-----------------------------------------------------------------------------
1379 class BasicAllFormatsLoadFS : public ShaderImageLoadStoreBase
1380 {
1381 	GLuint m_vao, m_vbo;
1382 
Setup()1383 	virtual long Setup()
1384 	{
1385 		m_vao = 0;
1386 		m_vbo = 0;
1387 		return NO_ERROR;
1388 	}
1389 
Run()1390 	virtual long Run()
1391 	{
1392 		if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1))
1393 			return NOT_SUPPORTED;
1394 
1395 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1396 
1397 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1398 			return ERROR;
1399 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1400 			return ERROR;
1401 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1402 			return ERROR;
1403 
1404 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT))
1405 			return ERROR;
1406 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1407 			return ERROR;
1408 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT))
1409 			return ERROR;
1410 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE))
1411 			return ERROR;
1412 
1413 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1414 			return ERROR;
1415 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1416 			return ERROR;
1417 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1418 			return ERROR;
1419 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1420 			return ERROR;
1421 
1422 		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1423 			return ERROR;
1424 
1425 		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1426 			return ERROR;
1427 
1428 		return NO_ERROR;
1429 	}
1430 
1431 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1432 	bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type)
1433 	{
1434 		const char* src_vs =
1435 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
1436 		GLuint			 program = BuildProgram(src_vs, GenFS(internalformat, expected_value).c_str());
1437 		const int		 kSize   = 11;
1438 		ShortByteData<T> d(kSize, value, internalformat, format);
1439 		GLuint			 texture;
1440 		glGenTextures(1, &texture);
1441 		GLuint unit = 1;
1442 		glBindTexture(GL_TEXTURE_2D, texture);
1443 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1444 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1445 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1446 		if (Shorts(internalformat))
1447 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1448 		else if (Bytes(internalformat))
1449 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1450 		else
1451 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1452 		glBindTexture(GL_TEXTURE_2D, 0);
1453 
1454 		glViewport(0, 0, kSize, kSize);
1455 		glClear(GL_COLOR_BUFFER_BIT);
1456 		glUseProgram(program);
1457 		glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1458 		glBindVertexArray(m_vao);
1459 
1460 		std::vector<T> out_data(kSize * kSize);
1461 		GLuint		   m_buffer;
1462 		glGenBuffers(1, &m_buffer);
1463 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1464 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1465 
1466 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1467 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1468 		T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1469 		for (int i = 0; i < kSize * kSize; ++i)
1470 		{
1471 			if (!Equal(map_data[i], expected_value, internalformat))
1472 			{
1473 				m_context.getTestContext().getLog()
1474 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1475 					<< ". Value should be: " << ToString(expected_value).c_str()
1476 					<< ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1477 					<< tcu::TestLog::EndMessage;
1478 				glUseProgram(0);
1479 				glDeleteProgram(program);
1480 				glDeleteTextures(1, &texture);
1481 				glDeleteBuffers(1, &m_buffer);
1482 				return false;
1483 			}
1484 		}
1485 		glUseProgram(0);
1486 		glDeleteProgram(program);
1487 		glDeleteTextures(1, &texture);
1488 		glDeleteBuffers(1, &m_buffer);
1489 		return true;
1490 	}
1491 
Cleanup()1492 	virtual long Cleanup()
1493 	{
1494 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1495 		glDeleteVertexArrays(1, &m_vao);
1496 		glDeleteBuffers(1, &m_vbo);
1497 		return NO_ERROR;
1498 	}
1499 
1500 	template <typename T>
GenFS(GLenum internalformat,const T & expected_value)1501 	std::string GenFS(GLenum internalformat, const T& expected_value)
1502 	{
1503 		std::ostringstream os;
1504 		os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat)
1505 		   << ", binding = 1) readonly uniform " << TypePrefix<T>()
1506 		   << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL "  " << TypePrefix<T>()
1507 		   << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1508 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  data[coord.y * KSIZE + coord.x] = v;" NL
1509 								 "  //data[coord.y * KSIZE + coord.x] = "
1510 		   << TypePrefix<T>() << "vec4" << expected_value << ";" NL "  discard;" NL "}";
1511 		return os.str();
1512 	}
1513 };
1514 
1515 class BasicAllFormatsLoadCS : public ShaderImageLoadStoreBase
1516 {
Setup()1517 	virtual long Setup()
1518 	{
1519 		return NO_ERROR;
1520 	}
1521 
1522 	template <typename T>
GenCS(GLenum internalformat,const T & expected_value)1523 	std::string GenCS(GLenum internalformat, const T& expected_value)
1524 	{
1525 		std::ostringstream os;
1526 		os << NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout("
1527 		   << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>()
1528 		   << "image2D g_image;" NL "layout(std430) buffer OutputBuffer {" NL "  " << TypePrefix<T>()
1529 		   << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
1530 			  "  "
1531 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  data[gl_LocalInvocationIndex] = v;" NL
1532 								 "  //data[gl_LocalInvocationIndex] = "
1533 		   << TypePrefix<T>() << "vec4" << expected_value << ";" NL "}";
1534 		return os.str();
1535 	}
1536 
Run()1537 	virtual long Run()
1538 	{
1539 		if (!ReadCS(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1540 			return ERROR;
1541 		if (!ReadCS(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1542 			return ERROR;
1543 		if (!ReadCS(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f), GL_RGBA, GL_FLOAT))
1544 			return ERROR;
1545 
1546 		if (!ReadCS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_INT))
1547 			return ERROR;
1548 		if (!ReadCS(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1549 			return ERROR;
1550 		if (!ReadCS(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_SHORT))
1551 			return ERROR;
1552 		if (!ReadCS(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4), GL_RGBA_INTEGER, GL_BYTE))
1553 			return ERROR;
1554 
1555 		if (!ReadCS(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1556 			return ERROR;
1557 		if (!ReadCS(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1558 			return ERROR;
1559 		if (!ReadCS(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1560 			return ERROR;
1561 		if (!ReadCS(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1562 			return ERROR;
1563 
1564 		if (!ReadCS(GL_RGBA8, vec4(1.0f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1565 			return ERROR;
1566 
1567 		if (!ReadCS(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1568 			return ERROR;
1569 
1570 		return NO_ERROR;
1571 	}
1572 
1573 	template <typename T>
ReadCS(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1574 	bool ReadCS(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type)
1575 	{
1576 		GLuint			 program = CreateComputeProgram(GenCS(internalformat, expected_value));
1577 		const int		 kSize   = 4;
1578 		ShortByteData<T> d(kSize, value, internalformat, format);
1579 		GLuint			 texture;
1580 		glGenTextures(1, &texture);
1581 
1582 		GLuint unit = 1;
1583 		glBindTexture(GL_TEXTURE_2D, texture);
1584 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1585 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1586 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1587 		if (Shorts(internalformat))
1588 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1589 		else if (Bytes(internalformat))
1590 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1591 		else
1592 			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1593 		glBindTexture(GL_TEXTURE_2D, 0);
1594 
1595 		glUseProgram(program);
1596 		glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1597 
1598 		std::vector<T> out_data(kSize * kSize);
1599 		GLuint		   m_buffer;
1600 		glGenBuffers(1, &m_buffer);
1601 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1602 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1603 
1604 		glDispatchCompute(1, 1, 1);
1605 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1606 		T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1607 		for (int i = 0; i < kSize * kSize; ++i)
1608 		{
1609 			if (!Equal(map_data[i], expected_value, internalformat))
1610 			{
1611 				m_context.getTestContext().getLog()
1612 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1613 					<< ". Value should be: " << ToString(expected_value).c_str()
1614 					<< ". Format is: " << FormatEnumToString(internalformat).c_str() << ". Unit is: " << unit << "."
1615 					<< tcu::TestLog::EndMessage;
1616 				glUseProgram(0);
1617 				glDeleteProgram(program);
1618 				glDeleteTextures(1, &texture);
1619 				glDeleteBuffers(1, &m_buffer);
1620 				return false;
1621 			}
1622 		}
1623 		glUseProgram(0);
1624 		glDeleteProgram(program);
1625 		glDeleteTextures(1, &texture);
1626 		glDeleteBuffers(1, &m_buffer);
1627 		return true;
1628 	}
1629 
Cleanup()1630 	virtual long Cleanup()
1631 	{
1632 		return NO_ERROR;
1633 	}
1634 };
1635 
1636 class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
1637 {
Run()1638 	virtual long Run()
1639 	{
1640 
1641 		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT))
1642 			return ERROR;
1643 		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 0.0f, 0.0f, 1.0f), GL_RED, GL_FLOAT))
1644 			return ERROR;
1645 		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(2.0f, 4.0f, 6.0f, 8.0f), GL_RGBA, GL_FLOAT))
1646 			return ERROR;
1647 
1648 		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_INT))
1649 			return ERROR;
1650 		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(2, 0, 0, 1), GL_RED_INTEGER, GL_INT))
1651 			return ERROR;
1652 		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_SHORT))
1653 			return ERROR;
1654 		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(2, -4, 6, -8), GL_RGBA_INTEGER, GL_BYTE))
1655 			return ERROR;
1656 
1657 		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
1658 			return ERROR;
1659 		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(14, 0, 0, 1), GL_RED_INTEGER, GL_UNSIGNED_INT))
1660 			return ERROR;
1661 		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_SHORT))
1662 			return ERROR;
1663 		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 2, 4, 6), GL_RGBA_INTEGER, GL_UNSIGNED_BYTE))
1664 			return ERROR;
1665 
1666 		if (!Read(GL_RGBA8, vec4(0.5f), vec4(1.0f), GL_RGBA, GL_UNSIGNED_BYTE))
1667 			return ERROR;
1668 		if (!Read(GL_RGBA8_SNORM, vec4(0.5f, 0.0f, 0.5f, -0.5f), vec4(1.0f, 0.0f, 1.0f, -1.0f), GL_RGBA, GL_BYTE))
1669 			return ERROR;
1670 
1671 		return NO_ERROR;
1672 	}
1673 
1674 	template <typename T>
Read(GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)1675 	bool Read(GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type)
1676 	{
1677 		GLuint program = CreateComputeProgram(GenCS(internalformat, expected_value));
1678 
1679 		const int		 kSize = 8;
1680 		ShortByteData<T> d(kSize, value, internalformat, format);
1681 		GLuint			 texture[2];
1682 		glGenTextures(2, texture);
1683 
1684 		/* read texture */
1685 		{
1686 			glBindTexture(GL_TEXTURE_2D, texture[0]);
1687 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1688 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1689 			glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1690 			if (Shorts(internalformat))
1691 				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datas[0]);
1692 			else if (Bytes(internalformat))
1693 				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.datab[0]);
1694 			else
1695 				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &d.data[0]);
1696 		}
1697 		/* write texture */
1698 		{
1699 			glBindTexture(GL_TEXTURE_2D, texture[1]);
1700 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1701 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1702 			glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1703 		}
1704 		glBindTexture(GL_TEXTURE_2D, 0);
1705 
1706 		glUseProgram(program);
1707 
1708 		glBindImageTexture(2, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
1709 		glBindImageTexture(3, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1710 
1711 		glDispatchCompute(1, 1, 1);
1712 
1713 		glBindTexture(GL_TEXTURE_2D, texture[1]);
1714 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1715 
1716 		GLuint		   c_program = CreateComputeProgram(GenC(expected_value));
1717 		std::vector<T> out_data(kSize * kSize);
1718 		GLuint		   m_buffer;
1719 		glGenBuffers(1, &m_buffer);
1720 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1721 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
1722 
1723 		glUseProgram(c_program);
1724 		glDispatchCompute(1, 1, 1);
1725 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1726 		T* map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1727 		for (int i = 0; i < kSize * kSize; ++i)
1728 		{
1729 			if (!Equal(map_data[i], expected_value, internalformat))
1730 			{
1731 				m_context.getTestContext().getLog()
1732 					<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[i]).c_str()
1733 					<< ". Value should be: " << ToString(expected_value).c_str()
1734 					<< ". Format is: " << FormatEnumToString(internalformat).c_str() << "." << tcu::TestLog::EndMessage;
1735 				glDeleteTextures(2, texture);
1736 				glUseProgram(0);
1737 				glDeleteProgram(program);
1738 				glDeleteProgram(c_program);
1739 				glDeleteBuffers(1, &m_buffer);
1740 				return false;
1741 			}
1742 		}
1743 		glDeleteTextures(2, texture);
1744 		glUseProgram(0);
1745 		glDeleteProgram(program);
1746 		glDeleteProgram(c_program);
1747 		glDeleteBuffers(1, &m_buffer);
1748 
1749 		return true;
1750 	}
1751 
1752 	template <typename T>
GenCS(GLenum internalformat,const T & expected_value)1753 	std::string GenCS(GLenum internalformat, const T& expected_value)
1754 	{
1755 		std::ostringstream os;
1756 		os << NL "#define KSIZE 8" NL "layout(local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "layout("
1757 		   << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform " << TypePrefix<T>()
1758 		   << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat)
1759 		   << ", binding = 3) writeonly uniform " << TypePrefix<T>()
1760 		   << "image2D g_image_write;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL "  "
1761 		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image_read, coord);" NL
1762 								 "  imageStore(g_image_write, coord, v+v);" NL "  //imageStore(g_image_write, coord, "
1763 		   << TypePrefix<T>() << "vec4" << expected_value << ");" NL "}";
1764 		return os.str();
1765 	}
1766 
1767 	template <typename T>
GenC(const T & value)1768 	std::string GenC(const T& value)
1769 	{
1770 		std::ostringstream os;
1771 		os << NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
1772 		   << TypePrefix<T>() << "sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL "  "
1773 		   << TypePrefix<T>()
1774 		   << "vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
1775 			  "  data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL
1776 			  "  //data[gl_LocalInvocationIndex] = "
1777 		   << TypePrefix<T>() << "vec4" << value << ";" NL "}";
1778 		return os.str();
1779 	}
1780 };
1781 //-----------------------------------------------------------------------------
1782 // 1.3.1 BasicAllTargetsStore
1783 //-----------------------------------------------------------------------------
1784 class BasicAllTargetsStoreFS : public ShaderImageLoadStoreBase
1785 {
1786 	GLuint m_vao;
1787 	GLuint m_vbo;
1788 
Setup()1789 	virtual long Setup()
1790 	{
1791 		m_vao = 0;
1792 		m_vbo = 0;
1793 		return NO_ERROR;
1794 	}
1795 
Run()1796 	virtual long Run()
1797 	{
1798 		if (!IsVSFSAvailable(0, 4))
1799 			return NOT_SUPPORTED;
1800 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1801 
1802 		if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1803 			return ERROR;
1804 		if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1805 			return ERROR;
1806 		if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1807 			return ERROR;
1808 		if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1809 			return ERROR;
1810 		if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1811 			return ERROR;
1812 		if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1813 			return ERROR;
1814 		if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1815 			return ERROR;
1816 		if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1817 			return ERROR;
1818 		if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1819 			return ERROR;
1820 		if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
1821 			return ERROR;
1822 		if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1823 			return ERROR;
1824 		if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
1825 			return ERROR;
1826 
1827 		return NO_ERROR;
1828 	}
1829 
Cleanup()1830 	virtual long Cleanup()
1831 	{
1832 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1833 		glDeleteVertexArrays(1, &m_vao);
1834 		glDeleteBuffers(1, &m_vbo);
1835 		glActiveTexture(GL_TEXTURE0);
1836 		return NO_ERROR;
1837 	}
1838 
1839 	template <typename T>
Write(int target,GLenum internalformat,const T & write_value,const T & expected_value)1840 	bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value)
1841 	{
1842 		const char* src_vs =
1843 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
1844 		const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, write_value).c_str());
1845 		GLuint		 textures[8];
1846 		glGenTextures(8, textures);
1847 
1848 		const int	  kSize = 11;
1849 		std::vector<T> data(kSize * kSize * 2);
1850 
1851 		glBindTexture(GL_TEXTURE_2D, textures[1]);
1852 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1853 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1854 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
1855 		glBindTexture(GL_TEXTURE_2D, 0);
1856 
1857 		glBindTexture(GL_TEXTURE_3D, textures[2]);
1858 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1859 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1860 		glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
1861 		glBindTexture(GL_TEXTURE_3D, 0);
1862 
1863 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
1864 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1865 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1866 		glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
1867 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
1868 
1869 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
1870 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1871 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1872 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
1873 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1874 
1875 		glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
1876 		glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 3D
1877 		glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // Cube
1878 		glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 2DArray
1879 
1880 		glUseProgram(program);
1881 		glBindVertexArray(m_vao);
1882 		glViewport(0, 0, kSize, kSize);
1883 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1884 
1885 		glActiveTexture(GL_TEXTURE1);
1886 		glBindTexture(GL_TEXTURE_2D, textures[1]);
1887 		glActiveTexture(GL_TEXTURE2);
1888 		glBindTexture(GL_TEXTURE_3D, textures[2]);
1889 		glActiveTexture(GL_TEXTURE3);
1890 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
1891 		glActiveTexture(GL_TEXTURE4);
1892 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
1893 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1894 
1895 		GLuint		   c_program = CreateComputeProgram(GenC(write_value));
1896 		std::vector<T> out_data2D(kSize * kSize * 6);
1897 		std::vector<T> out_data3D(kSize * kSize * 6);
1898 		std::vector<T> out_dataCube(kSize * kSize * 6);
1899 		std::vector<T> out_data2DArray(kSize * kSize * 6);
1900 		GLuint		   m_buffer[4];
1901 		glGenBuffers(4, m_buffer);
1902 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]);
1903 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1904 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
1905 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1906 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]);
1907 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1908 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
1909 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
1910 
1911 		glUseProgram(c_program);
1912 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1);
1913 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2);
1914 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3);
1915 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4);
1916 		glDispatchCompute(1, 1, 1);
1917 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1918 
1919 		bool status = true;
1920 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
1921 		T*  map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
1922 		int layers   = 2;
1923 		if (target == T2D)
1924 			layers = 1;
1925 		if (target == TCM)
1926 			layers = 6;
1927 		status	 = CompareValues(map_data, kSize, expected_value, internalformat, layers);
1928 		if (!status)
1929 			m_context.getTestContext().getLog()
1930 				<< tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
1931 				<< " format failed." << tcu::TestLog::EndMessage;
1932 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1933 
1934 		glDeleteTextures(8, textures);
1935 		glUseProgram(0);
1936 		glDeleteProgram(program);
1937 		glDeleteProgram(c_program);
1938 		glDeleteBuffers(4, m_buffer);
1939 
1940 		return status;
1941 	}
1942 
1943 	template <typename T>
GenFS(int target,GLenum internalformat,const T & write_value)1944 	std::string GenFS(int target, GLenum internalformat, const T& write_value)
1945 	{
1946 		std::ostringstream os;
1947 		switch (target)
1948 		{
1949 		case T2D:
1950 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform "
1951 			   << TypePrefix<T>() << "image2D g_image_2d;";
1952 			break;
1953 		case T3D:
1954 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
1955 			   << TypePrefix<T>() << "image3D g_image_3d;";
1956 			break;
1957 		case TCM:
1958 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
1959 			   << TypePrefix<T>() << "imageCube g_image_cube;";
1960 			break;
1961 		case T2DA:
1962 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform "
1963 			   << TypePrefix<T>() << "image2DArray g_image_2darray;";
1964 			break;
1965 		}
1966 		os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);";
1967 
1968 		switch (target)
1969 		{
1970 		case T2D:
1971 			os << NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");";
1972 			break;
1973 		case T3D:
1974 			os << NL "  imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1975 			   << ");" NL "  imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1976 			   << ");";
1977 			break;
1978 		case TCM:
1979 			os << NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1980 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1981 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value
1982 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value
1983 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value
1984 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value
1985 			   << ");";
1986 			break;
1987 		case T2DA:
1988 			os << NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
1989 			   << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
1990 			   << ");";
1991 			break;
1992 		}
1993 		os << NL "  discard;" NL "}";
1994 		return os.str();
1995 	}
1996 
1997 	template <typename T>
GenC(const T & write_value)1998 	std::string GenC(const T& write_value)
1999 	{
2000 		std::ostringstream os;
2001 		os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
2002 		   << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>()
2003 		   << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform "
2004 		   << TypePrefix<T>()
2005 		   << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL "  "
2006 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL
2007 								 "layout(std430, binding = 0) buffer OutputBuffer3D {" NL "  "
2008 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL
2009 								 "layout(std430, binding = 3) buffer OutputBufferCube {" NL "  "
2010 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL
2011 								 "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL "  "
2012 		   << TypePrefix<T>()
2013 		   << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL
2014 			  "  int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL
2015 			  "  int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL
2016 			  "  uint layer = uint(KSIZE * KSIZE);" NL
2017 			  "  g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL
2018 			  "  g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), "
2019 			  "0);" NL "  g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, "
2020 			  "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL "  g_buff_2darray.data[gl_LocalInvocationIndex] = "
2021 			  "texelFetch(g_sampler_2darray, "
2022 			  "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL
2023 			  "  g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, "
2024 			  "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL "  g_buff_cube.data[gl_LocalInvocationIndex] = "
2025 			  "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL
2026 			  "  g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, "
2027 			  "vec3(KSIZE,cubemap_i,cubemap_j));" NL "  g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = "
2028 			  "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL
2029 			  "  g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, "
2030 			  "vec3(cubemap_i,KSIZE,cubemap_j));" NL "  g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = "
2031 			  "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL
2032 			  "  g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, "
2033 			  "vec3(cubemap_i,cubemap_j,KSIZE));" NL "  //g_buff_2d.data[gl_LocalInvocationIndex] = "
2034 		   << write_value << ";" NL "}";
2035 		return os.str();
2036 	}
2037 };
2038 
2039 class BasicAllTargetsStoreCS : public ShaderImageLoadStoreBase
2040 {
Setup()2041 	virtual long Setup()
2042 	{
2043 		return NO_ERROR;
2044 	}
2045 
Run()2046 	virtual long Run()
2047 	{
2048 
2049 		if (!Write(T2D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2050 			return ERROR;
2051 		if (!Write(T2D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2052 			return ERROR;
2053 		if (!Write(T2D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2054 			return ERROR;
2055 		if (!Write(T3D, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2056 			return ERROR;
2057 		if (!Write(T3D, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2058 			return ERROR;
2059 		if (!Write(T3D, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2060 			return ERROR;
2061 		if (!Write(TCM, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2062 			return ERROR;
2063 		if (!Write(TCM, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2064 			return ERROR;
2065 		if (!Write(TCM, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2066 			return ERROR;
2067 		if (!Write(T2DA, GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2068 			return ERROR;
2069 		if (!Write(T2DA, GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2070 			return ERROR;
2071 		if (!Write(T2DA, GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2072 			return ERROR;
2073 
2074 		return NO_ERROR;
2075 	}
2076 
Cleanup()2077 	virtual long Cleanup()
2078 	{
2079 		glActiveTexture(GL_TEXTURE0);
2080 		return NO_ERROR;
2081 	}
2082 
2083 	template <typename T>
Write(int target,GLenum internalformat,const T & write_value,const T & expected_value)2084 	bool Write(int target, GLenum internalformat, const T& write_value, const T& expected_value)
2085 	{
2086 		const GLuint program = CreateComputeProgram(GenCS(target, internalformat, write_value));
2087 		GLuint		 textures[8];
2088 		glGenTextures(8, textures);
2089 
2090 		const int	  kSize = 11;
2091 		std::vector<T> data(kSize * kSize * 2);
2092 
2093 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2094 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2095 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2096 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2097 		glBindTexture(GL_TEXTURE_2D, 0);
2098 
2099 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2100 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2101 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2102 		glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2103 		glBindTexture(GL_TEXTURE_3D, 0);
2104 
2105 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2106 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2107 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2108 		glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2109 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2110 
2111 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2112 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2113 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2114 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2115 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2116 
2117 		glBindImageTexture(0, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
2118 		glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 3D
2119 		glBindImageTexture(2, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // Cube
2120 		glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 2DArray
2121 
2122 		glUseProgram(program);
2123 		glDispatchCompute(1, 1, 1);
2124 
2125 		glActiveTexture(GL_TEXTURE1);
2126 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2127 		glActiveTexture(GL_TEXTURE2);
2128 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2129 		glActiveTexture(GL_TEXTURE3);
2130 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2131 		glActiveTexture(GL_TEXTURE4);
2132 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2133 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
2134 
2135 		GLuint		   c_program = CreateComputeProgram(GenC(write_value));
2136 		std::vector<T> out_data2D(kSize * kSize * 6);
2137 		std::vector<T> out_data3D(kSize * kSize * 6);
2138 		std::vector<T> out_dataCube(kSize * kSize * 6);
2139 		std::vector<T> out_data2DArray(kSize * kSize * 6);
2140 		GLuint		   m_buffer[4];
2141 		glGenBuffers(4, m_buffer);
2142 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
2143 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2144 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
2145 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2146 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]);
2147 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2148 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]);
2149 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2150 
2151 		glUseProgram(c_program);
2152 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_2d"), 1);
2153 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_3d"), 2);
2154 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_cube"), 3);
2155 		glUniform1i(glGetUniformLocation(c_program, "g_sampler_2darray"), 4);
2156 
2157 		glDispatchCompute(1, 1, 1);
2158 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2159 
2160 		bool status = true;
2161 
2162 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2163 		T*  map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2164 		int layers   = 2;
2165 		if (target == T2D)
2166 			layers = 1;
2167 		if (target == TCM)
2168 			layers = 6;
2169 		status	 = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2170 		if (!status)
2171 			m_context.getTestContext().getLog()
2172 				<< tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2173 				<< " format failed." << tcu::TestLog::EndMessage;
2174 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2175 
2176 		glDeleteTextures(8, textures);
2177 		glUseProgram(0);
2178 		glDeleteProgram(program);
2179 		glDeleteProgram(c_program);
2180 		glDeleteBuffers(4, m_buffer);
2181 
2182 		return status;
2183 	}
2184 
2185 	template <typename T>
GenCS(int target,GLenum internalformat,const T & write_value)2186 	std::string GenCS(int target, GLenum internalformat, const T& write_value)
2187 	{
2188 		std::ostringstream os;
2189 		os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;";
2190 		switch (target)
2191 		{
2192 		case T2D:
2193 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform "
2194 			   << TypePrefix<T>() << "image2D g_image_2d;";
2195 			break;
2196 		case T3D:
2197 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
2198 			   << TypePrefix<T>() << "image3D g_image_3d;";
2199 			break;
2200 		case TCM:
2201 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) writeonly uniform "
2202 			   << TypePrefix<T>() << "imageCube g_image_cube;";
2203 			break;
2204 		case T2DA:
2205 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) writeonly uniform "
2206 			   << TypePrefix<T>() << "image2DArray g_image_2darray;";
2207 			break;
2208 		}
2209 		os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);";
2210 		switch (target)
2211 		{
2212 		case T2D:
2213 			os << NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>() << "vec4" << write_value << ");";
2214 			break;
2215 		case T3D:
2216 			os << NL "  imageStore(g_image_3d, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2217 			   << ");" NL "  imageStore(g_image_3d, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2218 			   << ");";
2219 			break;
2220 		case TCM:
2221 			os << NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2222 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2223 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4" << write_value
2224 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4" << write_value
2225 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4" << write_value
2226 			   << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4" << write_value
2227 			   << ");";
2228 			break;
2229 		case T2DA:
2230 			os << NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4" << write_value
2231 			   << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4" << write_value
2232 			   << ");";
2233 			break;
2234 		}
2235 		os << NL "}";
2236 		return os.str();
2237 	}
2238 
2239 	template <typename T>
GenC(const T & write_value)2240 	std::string GenC(const T& write_value)
2241 	{
2242 		std::ostringstream os;
2243 		os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL "uniform "
2244 		   << TypePrefix<T>() << "sampler2D g_sampler_2d;" NL "uniform " << TypePrefix<T>()
2245 		   << "sampler3D g_sampler_3d;" NL "uniform " << TypePrefix<T>() << "samplerCube g_sampler_cube;" NL "uniform "
2246 		   << TypePrefix<T>()
2247 		   << "sampler2DArray g_sampler_2darray;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL "  "
2248 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;" NL
2249 								 "layout(std430, binding = 1) buffer OutputBuffer3D {" NL "  "
2250 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;" NL
2251 								 "layout(std430, binding = 2) buffer OutputBufferCube {" NL "  "
2252 		   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;" NL
2253 								 "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL "  "
2254 		   << TypePrefix<T>()
2255 		   << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;" NL "void main() {" NL
2256 			  "  int cubemap_i = 2 * int(gl_LocalInvocationID.x) - KSIZE + 1;" NL
2257 			  "  int cubemap_j = 2 * int(gl_LocalInvocationID.y) - KSIZE + 1;" NL
2258 			  "  uint layer = uint(KSIZE * KSIZE);" NL
2259 			  "  g_buff_2d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_2d, ivec2(gl_LocalInvocationID), 0);" NL
2260 			  "  g_buff_3d.data[gl_LocalInvocationIndex] = texelFetch(g_sampler_3d, ivec3(gl_LocalInvocationID.xy, 0), "
2261 			  "0);" NL "  g_buff_3d.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_3d, "
2262 			  "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL "  g_buff_2darray.data[gl_LocalInvocationIndex] = "
2263 			  "texelFetch(g_sampler_2darray, "
2264 			  "ivec3(gl_LocalInvocationID.xy, 0), 0);" NL
2265 			  "  g_buff_2darray.data[gl_LocalInvocationIndex + layer] = texelFetch(g_sampler_2darray, "
2266 			  "ivec3(gl_LocalInvocationID.xy, 1), 0);" NL "  g_buff_cube.data[gl_LocalInvocationIndex] = "
2267 			  "texture(g_sampler_cube, vec3(KSIZE,cubemap_i,cubemap_j));" NL
2268 			  "  g_buff_cube.data[gl_LocalInvocationIndex + layer] = texture(g_sampler_cube, "
2269 			  "vec3(KSIZE,cubemap_i,cubemap_j));" NL "  g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = "
2270 			  "texture(g_sampler_cube, vec3(cubemap_i,KSIZE,cubemap_j));" NL
2271 			  "  g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = texture(g_sampler_cube, "
2272 			  "vec3(cubemap_i,KSIZE,cubemap_j));" NL "  g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = "
2273 			  "texture(g_sampler_cube, vec3(cubemap_i,cubemap_j,KSIZE));" NL
2274 			  "  g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = texture(g_sampler_cube, "
2275 			  "vec3(cubemap_i,cubemap_j,KSIZE));" NL "  //g_buff_2d.data[gl_LocalInvocationIndex] = "
2276 		   << write_value << ";" NL "}";
2277 		return os.str();
2278 	}
2279 };
2280 //-----------------------------------------------------------------------------
2281 // 1.3.2.1 BasicAllTargetsLoad
2282 //-----------------------------------------------------------------------------
2283 class BasicAllTargetsLoadFS : public ShaderImageLoadStoreBase
2284 {
2285 	GLuint m_vao;
2286 	GLuint m_vbo;
2287 
Setup()2288 	virtual long Setup()
2289 	{
2290 		m_vao = 0;
2291 		m_vbo = 0;
2292 		return NO_ERROR;
2293 	}
2294 
Run()2295 	virtual long Run()
2296 	{
2297 		if (!IsVSFSAvailable(0, 4) || !IsSSBInVSFSAvailable(4))
2298 			return NOT_SUPPORTED;
2299 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2300 
2301 		if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2302 				  GL_FLOAT))
2303 			return ERROR;
2304 		if (!Read(T2D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2305 			return ERROR;
2306 		if (!Read(T2D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2307 			return ERROR;
2308 		if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2309 				  GL_FLOAT))
2310 			return ERROR;
2311 		if (!Read(T3D, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2312 			return ERROR;
2313 		if (!Read(T3D, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2314 			return ERROR;
2315 		if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2316 				  GL_FLOAT))
2317 			return ERROR;
2318 		if (!Read(TCM, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2319 			return ERROR;
2320 		if (!Read(TCM, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2321 			return ERROR;
2322 		if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2323 				  GL_FLOAT))
2324 			return ERROR;
2325 		if (!Read(T2DA, GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2326 			return ERROR;
2327 		if (!Read(T2DA, GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000), GL_RGBA_INTEGER,
2328 				  GL_UNSIGNED_INT))
2329 			return ERROR;
2330 
2331 		return NO_ERROR;
2332 	}
2333 
Cleanup()2334 	virtual long Cleanup()
2335 	{
2336 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2337 		glDeleteVertexArrays(1, &m_vao);
2338 		glDeleteBuffers(1, &m_vbo);
2339 		return NO_ERROR;
2340 	}
2341 
2342 	template <typename T>
Read(int target,GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)2343 	bool Read(int target, GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type)
2344 	{
2345 		const char* src_vs =
2346 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
2347 		const GLuint program = BuildProgram(src_vs, GenFS(target, internalformat, expected_value).c_str());
2348 		GLuint		 textures[8];
2349 		glGenTextures(8, textures);
2350 
2351 		const int	  kSize = 11;
2352 		std::vector<T> data(kSize * kSize * 2, value);
2353 
2354 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2355 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2356 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2357 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2358 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2359 		glBindTexture(GL_TEXTURE_2D, 0);
2360 
2361 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2362 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2363 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2364 		glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2365 		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2366 		glBindTexture(GL_TEXTURE_3D, 0);
2367 
2368 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2369 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2370 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2371 		glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2372 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2373 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2374 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2375 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2376 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2377 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2378 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2379 
2380 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2381 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2382 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2383 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2384 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2385 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2386 
2387 		glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
2388 		glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 3D
2389 		glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // Cube
2390 		glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 2DArray
2391 
2392 		std::vector<T> out_data2D(kSize * kSize * 6);
2393 		std::vector<T> out_data3D(kSize * kSize * 6);
2394 		std::vector<T> out_dataCube(kSize * kSize * 6);
2395 		std::vector<T> out_data2DArray(kSize * kSize * 6);
2396 		GLuint		   m_buffer[4];
2397 		glGenBuffers(4, m_buffer);
2398 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[0]);
2399 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2400 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[1]);
2401 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2402 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[2]);
2403 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2404 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[3]);
2405 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2406 
2407 		glUseProgram(program);
2408 		glClear(GL_COLOR_BUFFER_BIT);
2409 		glBindVertexArray(m_vao);
2410 		glViewport(0, 0, kSize, kSize);
2411 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2412 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2413 
2414 		bool status = true;
2415 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2416 		T*  map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2417 		int layers   = 2;
2418 		if (target == T2D)
2419 			layers = 1;
2420 		if (target == TCM)
2421 			layers = 6;
2422 		status	 = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2423 		if (!status)
2424 			m_context.getTestContext().getLog()
2425 				<< tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2426 				<< " format failed." << tcu::TestLog::EndMessage;
2427 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2428 
2429 		glUseProgram(0);
2430 		glDeleteProgram(program);
2431 		glDeleteTextures(8, textures);
2432 		glDeleteBuffers(4, m_buffer);
2433 
2434 		return status;
2435 	}
2436 
2437 	template <typename T>
GenFS(int target,GLenum internalformat,const T & expected_value)2438 	std::string GenFS(int target, GLenum internalformat, const T& expected_value)
2439 	{
2440 		std::ostringstream os;
2441 		os << NL "#define KSIZE 11";
2442 		switch (target)
2443 		{
2444 		case T2D:
2445 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform "
2446 			   << TypePrefix<T>()
2447 			   << "image2D g_image_2d;" NL "layout(std430, binding = 1) buffer OutputBuffer2D {" NL "  "
2448 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;";
2449 			break;
2450 		case T3D:
2451 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform "
2452 			   << TypePrefix<T>()
2453 			   << "image3D g_image_3d;" NL "layout(std430, binding = 0) buffer OutputBuffer3D {" NL "  "
2454 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;";
2455 			break;
2456 		case TCM:
2457 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
2458 			   << TypePrefix<T>()
2459 			   << "imageCube g_image_cube;" NL "layout(std430, binding = 3) buffer OutputBufferCube {" NL "  "
2460 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;";
2461 			break;
2462 		case T2DA:
2463 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform "
2464 			   << TypePrefix<T>()
2465 			   << "image2DArray g_image_2darray;" NL "layout(std430, binding = 2) buffer OutputBuffer2DArray {" NL "  "
2466 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;";
2467 			break;
2468 		}
2469 		os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2470 				 "  int coordIndex = coord.x + KSIZE * coord.y;" NL "  int layer = int(KSIZE * KSIZE);" NL "  "
2471 		   << TypePrefix<T>() << "vec4 v;";
2472 
2473 		switch (target)
2474 		{
2475 		case T2D:
2476 			os << NL "  v = imageLoad(g_image_2d, coord);" NL "  g_buff_2d.data[coordIndex] = v;";
2477 			break;
2478 		case T3D:
2479 			os << NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL "  g_buff_3d.data[coordIndex] = v;" NL
2480 					 "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL "  g_buff_3d.data[coordIndex + layer] = v;";
2481 			break;
2482 		case TCM:
2483 			os << NL
2484 				"  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  g_buff_cube.data[coordIndex] = v;" NL
2485 				"  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  g_buff_cube.data[coordIndex + layer] = v;" NL
2486 				"  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
2487 				"  g_buff_cube.data[coordIndex + 2 * layer] = v;" NL
2488 				"  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
2489 				"  g_buff_cube.data[coordIndex + 3 * layer] = v;" NL
2490 				"  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
2491 				"  g_buff_cube.data[coordIndex + 4 * layer] = v;" NL
2492 				"  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL "  g_buff_cube.data[coordIndex + 5 * layer] = v;";
2493 			break;
2494 		case T2DA:
2495 			os << NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL "  g_buff_2darray.data[coordIndex] = v;" NL
2496 					 "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
2497 					 "  g_buff_2darray.data[coordIndex + layer] = v;";
2498 			break;
2499 		}
2500 		os << NL "  //g_buff_2d.data[coordIndex] = " << expected_value << ";" NL "}";
2501 		return os.str();
2502 	}
2503 };
2504 
2505 class BasicAllTargetsLoadCS : public ShaderImageLoadStoreBase
2506 {
Setup()2507 	virtual long Setup()
2508 	{
2509 		return NO_ERROR;
2510 	}
2511 
Run()2512 	virtual long Run()
2513 	{
2514 		if (!Read(T2D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2515 				  GL_FLOAT))
2516 			return ERROR;
2517 		if (!Read(T2D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2518 				  ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2519 			return ERROR;
2520 		if (!Read(T2D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2521 				  uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2522 			return ERROR;
2523 		if (!Read(T3D, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2524 				  GL_FLOAT))
2525 			return ERROR;
2526 		if (!Read(T3D, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2527 				  ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2528 			return ERROR;
2529 		if (!Read(T3D, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2530 				  uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2531 			return ERROR;
2532 		if (!Read(TCM, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2533 				  GL_FLOAT))
2534 			return ERROR;
2535 		if (!Read(TCM, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2536 				  ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2537 			return ERROR;
2538 		if (!Read(TCM, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2539 				  uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2540 			return ERROR;
2541 		if (!Read(T2DA, GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f), GL_RGBA,
2542 				  GL_FLOAT))
2543 			return ERROR;
2544 		if (!Read(T2DA, GL_RGBA32I, ivec4(-0x7fffffff, 0x7fffffff, -200, 3000),
2545 				  ivec4(-0x7fffffff, 0x7fffffff, -200, 3000), GL_RGBA_INTEGER, GL_INT))
2546 			return ERROR;
2547 		if (!Read(T2DA, GL_RGBA32UI, uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000),
2548 				  uvec4(0xffffffffu, 0x7fffffff, 0x80000000, 3000), GL_RGBA_INTEGER, GL_UNSIGNED_INT))
2549 			return ERROR;
2550 
2551 		return NO_ERROR;
2552 	}
2553 
Cleanup()2554 	virtual long Cleanup()
2555 	{
2556 		return NO_ERROR;
2557 	}
2558 
2559 	template <typename T>
Read(int target,GLenum internalformat,const T & value,const T & expected_value,GLenum format,GLenum type)2560 	bool Read(int target, GLenum internalformat, const T& value, const T& expected_value, GLenum format, GLenum type)
2561 	{
2562 		const GLuint program = CreateComputeProgram(GenCS(target, internalformat, expected_value));
2563 		GLuint		 textures[8];
2564 		glGenTextures(8, textures);
2565 
2566 		const int	  kSize = 11;
2567 		std::vector<T> data(kSize * kSize * 2, value);
2568 
2569 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2570 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2571 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2572 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2573 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2574 		glBindTexture(GL_TEXTURE_2D, 0);
2575 
2576 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2577 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2578 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2579 		glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 2);
2580 		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2581 		glBindTexture(GL_TEXTURE_3D, 0);
2582 
2583 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2584 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2585 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2586 		glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2587 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2588 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2589 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2590 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2591 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2592 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, format, type, &data[0]);
2593 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2594 
2595 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2596 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2597 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2598 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 2);
2599 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 2, format, type, &data[0]);
2600 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2601 
2602 		glBindImageTexture(2, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
2603 		glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 3D
2604 		glBindImageTexture(3, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // Cube
2605 		glBindImageTexture(1, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 2DArray
2606 
2607 		std::vector<T> out_data2D(kSize * kSize * 6);
2608 		std::vector<T> out_data3D(kSize * kSize * 6);
2609 		std::vector<T> out_dataCube(kSize * kSize * 6);
2610 		std::vector<T> out_data2DArray(kSize * kSize * 6);
2611 		GLuint		   m_buffer[4];
2612 		glGenBuffers(4, m_buffer);
2613 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer[0]);
2614 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2615 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_buffer[1]);
2616 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2617 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_buffer[2]);
2618 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2619 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_buffer[3]);
2620 		glBufferData(GL_SHADER_STORAGE_BUFFER, 6 * kSize * kSize * 4 * 4, &out_dataCube[0], GL_STATIC_DRAW);
2621 
2622 		glUseProgram(program);
2623 		glDispatchCompute(1, 1, 1);
2624 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2625 
2626 		bool status = true;
2627 
2628 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer[target]);
2629 		T*  map_data = (T*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 6 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2630 		int layers   = 2;
2631 		if (target == T2D)
2632 			layers = 1;
2633 		if (target == TCM)
2634 			layers = 6;
2635 		status	 = CompareValues(map_data, kSize, expected_value, internalformat, layers);
2636 		if (!status)
2637 			m_context.getTestContext().getLog()
2638 				<< tcu::TestLog::Message << target << " target, " << FormatEnumToString(internalformat).c_str()
2639 				<< " format failed." << tcu::TestLog::EndMessage;
2640 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2641 
2642 		glUseProgram(0);
2643 		glDeleteProgram(program);
2644 		glDeleteTextures(8, textures);
2645 		glDeleteBuffers(4, m_buffer);
2646 
2647 		return status;
2648 	}
2649 
2650 	template <typename T>
GenCS(int target,GLenum internalformat,const T & expected_value)2651 	std::string GenCS(int target, GLenum internalformat, const T& expected_value)
2652 	{
2653 		std::ostringstream os;
2654 		os << NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;";
2655 		switch (target)
2656 		{
2657 		case T2D:
2658 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) readonly uniform "
2659 			   << TypePrefix<T>()
2660 			   << "image2D g_image_2d;" NL "layout(std430, binding = 0) buffer OutputBuffer2D {" NL "  "
2661 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE];" NL "} g_buff_2d;";
2662 			break;
2663 		case T3D:
2664 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) readonly uniform "
2665 			   << TypePrefix<T>()
2666 			   << "image3D g_image_3d;" NL "layout(std430, binding = 1) buffer OutputBuffer3D {" NL "  "
2667 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_3d;";
2668 			break;
2669 		case TCM:
2670 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
2671 			   << TypePrefix<T>()
2672 			   << "imageCube g_image_cube;" NL "layout(std430, binding = 2) buffer OutputBufferCube {" NL "  "
2673 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*6];" NL "} g_buff_cube;";
2674 			break;
2675 		case T2DA:
2676 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform "
2677 			   << TypePrefix<T>()
2678 			   << "image2DArray g_image_2darray;" NL "layout(std430, binding = 3) buffer OutputBuffer2DArray {" NL "  "
2679 			   << TypePrefix<T>() << "vec4 data[KSIZE*KSIZE*2];" NL "} g_buff_2darray;";
2680 			break;
2681 		}
2682 		os << NL "void main() {" NL "  ivec3 coord = ivec3(gl_LocalInvocationID.xy, 0);" NL
2683 				 "  uint layer = uint(KSIZE * KSIZE);" NL "  "
2684 		   << TypePrefix<T>() << "vec4 v;";
2685 		switch (target)
2686 		{
2687 		case T2D:
2688 			os << NL "  v = imageLoad(g_image_2d, coord.xy);" NL "  g_buff_2d.data[gl_LocalInvocationIndex] = v;";
2689 			break;
2690 		case T3D:
2691 			os << NL "  v = imageLoad(g_image_3d, coord);" NL "  g_buff_3d.data[gl_LocalInvocationIndex] = v;" NL
2692 					 "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
2693 					 "  g_buff_3d.data[gl_LocalInvocationIndex + layer] = v;";
2694 			break;
2695 		case TCM:
2696 			os << NL "  v = imageLoad(g_image_cube, coord);" NL "  g_buff_cube.data[gl_LocalInvocationIndex] = v;" NL
2697 					 "  v = imageLoad(g_image_cube, ivec3(coord.xy, 1));" NL
2698 					 "  g_buff_cube.data[gl_LocalInvocationIndex + layer] = v;" NL
2699 					 "  v = imageLoad(g_image_cube, ivec3(coord.xy, 2));" NL
2700 					 "  g_buff_cube.data[gl_LocalInvocationIndex + 2u * layer] = v;" NL
2701 					 "  v = imageLoad(g_image_cube, ivec3(coord.xy, 3));" NL
2702 					 "  g_buff_cube.data[gl_LocalInvocationIndex + 3u * layer] = v;" NL
2703 					 "  v = imageLoad(g_image_cube, ivec3(coord.xy, 4));" NL
2704 					 "  g_buff_cube.data[gl_LocalInvocationIndex + 4u * layer] = v;" NL
2705 					 "  v = imageLoad(g_image_cube, ivec3(coord.xy, 5));" NL
2706 					 "  g_buff_cube.data[gl_LocalInvocationIndex + 5u * layer] = v;";
2707 			break;
2708 		case T2DA:
2709 			os << NL "  v = imageLoad(g_image_2darray, coord);" NL
2710 					 "  g_buff_2darray.data[gl_LocalInvocationIndex] = v;" NL
2711 					 "  v = imageLoad(g_image_2darray, ivec3(coord.xy, 1));" NL
2712 					 "  g_buff_2darray.data[gl_LocalInvocationIndex + layer] = v;";
2713 			break;
2714 		}
2715 		os << NL "  //g_buff_2d.data[gl_LocalInvocationIndex] = " << expected_value << ";" NL "}";
2716 		return os.str();
2717 	}
2718 };
2719 //-----------------------------------------------------------------------------
2720 // 1.3.3 BasicAllTargetsAtomic
2721 //-----------------------------------------------------------------------------
2722 class BasicAllTargetsAtomicFS : public ShaderImageLoadStoreBase
2723 {
2724 	GLuint m_vao;
2725 	GLuint m_vbo;
2726 
Setup()2727 	virtual long Setup()
2728 	{
2729 		m_vao = 0;
2730 		m_vbo = 0;
2731 		return NO_ERROR;
2732 	}
2733 
Run()2734 	virtual long Run()
2735 	{
2736 		if (!IsImageAtomicSupported())
2737 			return NOT_SUPPORTED;
2738 		if (!IsVSFSAvailable(0, 4))
2739 			return NOT_SUPPORTED;
2740 		if (!AreOutputsAvailable(5))
2741 			return NOT_SUPPORTED;
2742 		if (!IsSSBInVSFSAvailable(1))
2743 			return NOT_SUPPORTED;
2744 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2745 
2746 		if (!Atomic<GLint>(GL_R32I))
2747 			return ERROR;
2748 		if (!Atomic<GLuint>(GL_R32UI))
2749 			return ERROR;
2750 
2751 		return NO_ERROR;
2752 	}
2753 
Cleanup()2754 	virtual long Cleanup()
2755 	{
2756 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2757 		glDeleteVertexArrays(1, &m_vao);
2758 		glDeleteBuffers(1, &m_vbo);
2759 		return NO_ERROR;
2760 	}
2761 
2762 	template <typename T>
Atomic(GLenum internalformat)2763 	bool Atomic(GLenum internalformat)
2764 	{
2765 		const char* src_vs =
2766 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
2767 		const GLuint program = BuildProgram(src_vs, GenFS<T>(internalformat).c_str(), false, true);
2768 		GLuint		 textures[8];
2769 		GLuint		 buffer;
2770 		glGenTextures(8, textures);
2771 		glGenBuffers(1, &buffer);
2772 
2773 		const int	  kSize = 11;
2774 		std::vector<T> data(kSize * kSize * 3);
2775 
2776 		glBindTexture(GL_TEXTURE_2D, textures[1]);
2777 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2778 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2779 		glTexStorage2D(GL_TEXTURE_2D, 1, internalformat, kSize, kSize);
2780 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2781 		glBindTexture(GL_TEXTURE_2D, 0);
2782 
2783 		glBindTexture(GL_TEXTURE_3D, textures[2]);
2784 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2785 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2786 		glTexStorage3D(GL_TEXTURE_3D, 1, internalformat, kSize, kSize, 3);
2787 		glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]);
2788 		glBindTexture(GL_TEXTURE_3D, 0);
2789 
2790 		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2791 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2792 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2793 		glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalformat, kSize, kSize);
2794 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2795 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2796 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2797 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2798 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2799 		glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 0, 0, kSize, kSize, Format<T>(), Type<T>(), &data[0]);
2800 		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2801 
2802 		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2803 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2804 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2805 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, internalformat, kSize, kSize, 3);
2806 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 3, Format<T>(), Type<T>(), &data[0]);
2807 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2808 
2809 		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D
2810 		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // 3D
2811 		glBindImageTexture(0, textures[4], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // Cube
2812 		glBindImageTexture(3, textures[7], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // 2DArray
2813 
2814 		std::vector<ivec4> o_data(kSize * kSize);
2815 		GLuint			   m_buffer;
2816 		glGenBuffers(1, &m_buffer);
2817 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
2818 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
2819 
2820 		glUseProgram(program);
2821 		glClear(GL_COLOR_BUFFER_BIT);
2822 		glBindVertexArray(m_vao);
2823 		glViewport(0, 0, kSize, kSize);
2824 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2825 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2826 
2827 		bool status = true;
2828 
2829 		ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
2830 		for (int i = 0; i < kSize * kSize; ++i)
2831 		{
2832 			if (!Equal(out_data[i], ivec4(10, 10, 10, 10), 0))
2833 			{
2834 				status = false;
2835 				m_context.getTestContext().getLog()
2836 					<< tcu::TestLog::Message << "[" << i
2837 					<< "] Atomic operation check failed. (operation/target coded: " << ToString(out_data[i]).c_str()
2838 					<< ")" << tcu::TestLog::EndMessage;
2839 			}
2840 		}
2841 
2842 		glUseProgram(0);
2843 		glDeleteProgram(program);
2844 		glDeleteTextures(8, textures);
2845 		glDeleteBuffers(1, &buffer);
2846 		glDeleteBuffers(1, &m_buffer);
2847 
2848 		return status;
2849 	}
2850 
2851 	template <typename T>
GenFS(GLenum internalformat)2852 	std::string GenFS(GLenum internalformat)
2853 	{
2854 		std::ostringstream os;
2855 		os << NL "#define KSIZE 11" NL "layout(" << FormatEnumToString(internalformat)
2856 		   << ", binding = 1) coherent uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2857 		   << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform " << TypePrefix<T>()
2858 		   << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
2859 		   << ", binding = 0) coherent uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2860 		   << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform " << TypePrefix<T>()
2861 		   << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL
2862 			  "  ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
2863 		   << TypePrefix<T>() << "vec2 t(int i) {" NL "  return " << TypePrefix<T>()
2864 		   << "vec2(i);" NL "}" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2865 			  "  int coordIndex = coord.x + KSIZE * coord.y;" NL "  o_color[coordIndex] = ivec4(coordIndex);" NL
2866 			  "  if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color[coordIndex].x = 1;" NL
2867 			  "  else if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color[coordIndex].x = 2;" NL
2868 			  "  else if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color[coordIndex].x = 3;" NL
2869 			  "  else if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color[coordIndex].x = 4;" NL
2870 			  "  else if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color[coordIndex].x = 5;" NL
2871 			  "  else if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color[coordIndex].x = 6;" NL
2872 			  "  else if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color[coordIndex].x = 7;" NL
2873 			  "  else if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color[coordIndex].x = "
2874 			  "8;" NL "  else o_color[coordIndex].x = 10;" NL
2875 			  "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].y = 1;" NL
2876 			  "  else if (imageAtomicMin(g_image_3d, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].y = 2;" NL
2877 			  "  else if (imageAtomicMax(g_image_3d, ivec3(coord, 2), t(4).x) != t(2).x) o_color[coordIndex].y = 3;" NL
2878 			  "  else if (imageAtomicAnd(g_image_3d, ivec3(coord, 2), t(0).x) != t(4).x) o_color[coordIndex].y = 4;" NL
2879 			  "  else if (imageAtomicOr(g_image_3d, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].y = 5;" NL
2880 			  "  else if (imageAtomicXor(g_image_3d, ivec3(coord, 2), t(4).x) != t(7).x) o_color[coordIndex].y = 6;" NL
2881 			  "  else if (imageAtomicExchange(g_image_3d, ivec3(coord, 2), t(1).x) != t(3).x) o_color[coordIndex].y = "
2882 			  "7;" NL "  else if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) "
2883 			  "o_color[coordIndex].y = 8;" NL "  else o_color[coordIndex].y = 10;" NL
2884 			  "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 3), t(2).x) != t(0).x) o_color[coordIndex].z = 1;" NL
2885 			  "  else if (imageAtomicMin(g_image_cube, ivec3(coord, 3), t(3).x) != t(2).x) o_color[coordIndex].z = "
2886 			  "2;" NL "  else if (imageAtomicMax(g_image_cube, ivec3(coord, 3), t(4).x) != t(2).x) "
2887 			  "o_color[coordIndex].z = 3;" NL "  else if (imageAtomicAnd(g_image_cube, ivec3(coord, 3), "
2888 			  "t(0).x) != t(4).x) o_color[coordIndex].z = 4;" NL
2889 			  "  else if (imageAtomicOr(g_image_cube, ivec3(coord, 3), t(7).x) != t(0).x) o_color[coordIndex].z = 5;" NL
2890 			  "  else if (imageAtomicXor(g_image_cube, ivec3(coord, 3), t(4).x) != t(7).x) o_color[coordIndex].z = "
2891 			  "6;" NL "  else if (imageAtomicExchange(g_image_cube, ivec3(coord, 3), t(1).x) != t(3).x) "
2892 			  "o_color[coordIndex].z = 7;" NL "  else if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 3), "
2893 			  "t(1).x, t(6).x) != t(1).x) o_color[coordIndex].z = 8;" NL "  else o_color[coordIndex].z = 10;" NL
2894 			  "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 2), t(2).x) != t(0).x) o_color[coordIndex].w = 1;" NL
2895 			  "  else if (imageAtomicMin(g_image_2darray, ivec3(coord, 2), t(3).x) != t(2).x) o_color[coordIndex].w = "
2896 			  "2;" NL "  else if (imageAtomicMax(g_image_2darray, ivec3(coord, 2), t(4).x) != t(2).x) "
2897 			  "o_color[coordIndex].w = 3;" NL "  else if (imageAtomicAnd(g_image_2darray, ivec3(coord, 2), "
2898 			  "t(0).x) != t(4).x) o_color[coordIndex].w = 4;" NL
2899 			  "  else if (imageAtomicOr(g_image_2darray, ivec3(coord, 2), t(7).x) != t(0).x) o_color[coordIndex].w = "
2900 			  "5;" NL "  else if (imageAtomicXor(g_image_2darray, ivec3(coord, 2), t(4).x) != t(7).x) "
2901 			  "o_color[coordIndex].w = 6;" NL "  else if (imageAtomicExchange(g_image_2darray, ivec3(coord, "
2902 			  "2), t(1).x) != t(3).x) o_color[coordIndex].w = 7;" NL
2903 			  "  else if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 2), t(1).x, t(6).x) != t(1).x) "
2904 			  "o_color[coordIndex].w = 8;" NL "  else o_color[coordIndex].w = 10;" NL "  discard;" NL "}";
2905 		return os.str();
2906 	}
2907 };
2908 //-----------------------------------------------------------------------------
2909 // LoadStoreMachine
2910 //-----------------------------------------------------------------------------
2911 class LoadStoreMachine : public ShaderImageLoadStoreBase
2912 {
2913 	GLuint m_vao;
2914 	GLuint m_buffer;
2915 	int	m_stage;
2916 
Setup()2917 	virtual long Setup()
2918 	{
2919 		glEnable(GL_RASTERIZER_DISCARD);
2920 		glGenVertexArrays(1, &m_vao);
2921 		glGenBuffers(1, &m_buffer);
2922 		return NO_ERROR;
2923 	}
2924 
Cleanup()2925 	virtual long Cleanup()
2926 	{
2927 		glDisable(GL_RASTERIZER_DISCARD);
2928 		glDeleteVertexArrays(1, &m_vao);
2929 		glDeleteBuffers(1, &m_buffer);
2930 		return NO_ERROR;
2931 	}
2932 
2933 	template <typename T>
Write(GLenum internalformat,const T & write_value,const T & expected_value)2934 	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2935 	{
2936 		const GLenum targets[]	 = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY };
2937 		const int	kTargets	  = sizeof(targets) / sizeof(targets[0]);
2938 		const int	kSize		   = 100;
2939 		GLuint		 program_store = 0;
2940 		GLuint		 program_load  = 0;
2941 		if (m_stage == 0)
2942 		{ // VS
2943 			const char* src_fs = NL "void main() {" NL "  discard;" NL "}";
2944 			program_store	  = BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), src_fs);
2945 			program_load	   = BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), src_fs);
2946 		}
2947 		else if (m_stage == 4)
2948 		{ // CS
2949 			program_store = CreateComputeProgram(GenStoreShader(m_stage, internalformat, write_value));
2950 			program_load  = CreateComputeProgram(GenLoadShader(m_stage, internalformat, expected_value));
2951 		}
2952 		GLuint textures[kTargets];
2953 		glGenTextures(kTargets, textures);
2954 
2955 		for (int i = 0; i < kTargets; ++i)
2956 		{
2957 			glBindTexture(targets[i], textures[i]);
2958 			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2959 			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2960 
2961 			if (targets[i] == GL_TEXTURE_2D)
2962 			{
2963 				glTexStorage2D(targets[i], 1, internalformat, kSize, 1);
2964 			}
2965 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
2966 			{
2967 				glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2);
2968 			}
2969 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
2970 			{
2971 				glTexStorage2D(targets[i], 1, internalformat, kSize, kSize);
2972 			}
2973 		}
2974 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat); // 2D
2975 		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 3D
2976 		glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // Cube
2977 		glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);  // 2DArray
2978 
2979 		std::vector<ivec4> b_data(kSize);
2980 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
2981 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW);
2982 
2983 		glUseProgram(program_store);
2984 		glBindVertexArray(m_vao);
2985 		if (m_stage == 4)
2986 		{ // CS
2987 			glDispatchCompute(1, 1, 1);
2988 		}
2989 		else if (m_stage == 0)
2990 		{ // VS
2991 			glDrawArrays(GL_POINTS, 0, kSize);
2992 		}
2993 		bool status = true;
2994 		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2995 
2996 		glBindImageTexture(3, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat); // 2D
2997 		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 3D
2998 		glBindImageTexture(1, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // Cube
2999 		glBindImageTexture(0, textures[3], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);  // 2DArray
3000 
3001 		glUseProgram(program_load);
3002 		if (m_stage == 0)
3003 		{ // VS
3004 			glDrawArrays(GL_POINTS, 0, kSize);
3005 		}
3006 		else if (m_stage == 4)
3007 		{ // CS
3008 			glDispatchCompute(1, 1, 1);
3009 		}
3010 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3011 
3012 		ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT);
3013 		for (int i = 0; i < kSize; ++i)
3014 		{
3015 			if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0))
3016 			{
3017 				status = false;
3018 				m_context.getTestContext().getLog()
3019 					<< tcu::TestLog::Message << "[" << i << "] load/store operation check failed. ("
3020 					<< ToString(out_data[i]).c_str() << ")" << tcu::TestLog::EndMessage;
3021 			}
3022 		}
3023 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3024 		glUseProgram(0);
3025 		glDeleteProgram(program_store);
3026 		glDeleteProgram(program_load);
3027 		glDeleteTextures(kTargets, textures);
3028 		return status;
3029 	}
3030 
3031 	template <typename T>
GenStoreShader(int stage,GLenum internalformat,const T & write_value)3032 	std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
3033 	{
3034 		std::ostringstream os;
3035 		if (stage == 4)
3036 		{ // CS
3037 			os << NL "#define KSIZE 100" NL "layout(local_size_x = KSIZE) in;";
3038 		}
3039 		os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) writeonly uniform "
3040 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3041 		   << ", binding = 2) writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3042 		   << FormatEnumToString(internalformat) << ", binding = 0) writeonly uniform " << TypePrefix<T>()
3043 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
3044 		   << ", binding = 3) writeonly uniform " << TypePrefix<T>()
3045 		   << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL "  ivec4 o_color;" NL "};" NL
3046 			  "void main() {" NL "  "
3047 		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color) + " << TypePrefix<T>() << "vec4"
3048 		   << write_value
3049 		   << ";" NL "  int g_index[6] = int[](o_color.x, o_color.y, o_color.z, o_color.w, o_color.r, o_color.g);";
3050 		if (stage == 0)
3051 		{ // VS
3052 			os << NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
3053 		}
3054 		else if (stage == 4)
3055 		{ // CS
3056 			os << NL "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
3057 		}
3058 		os << NL "  imageStore(g_image_2d, coord, g_value);" NL
3059 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
3060 				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
3061 				 "  for (int i = 0; i < 6; ++i) {" NL
3062 				 "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
3063 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
3064 				 "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL "}";
3065 		return os.str();
3066 	}
3067 
3068 	template <typename T>
GenLoadShader(int stage,GLenum internalformat,const T & expected_value)3069 	std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
3070 	{
3071 		std::ostringstream os;
3072 		os << NL "#define KSIZE 100";
3073 		if (stage == 4)
3074 		{ // CS
3075 			os << NL "layout(local_size_x = KSIZE) in;";
3076 		}
3077 		os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) readonly uniform "
3078 		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3079 		   << ", binding = 2) readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3080 		   << FormatEnumToString(internalformat) << ", binding = 1) readonly uniform " << TypePrefix<T>()
3081 		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
3082 		   << ", binding = 0) readonly uniform " << TypePrefix<T>()
3083 		   << "image2DArray g_image_2darray;" NL "layout(std430) buffer out_data {" NL "  ivec4 o_color[KSIZE];" NL
3084 			  "};" NL "void main() {";
3085 
3086 		if (stage == 0)
3087 		{ // VS
3088 			os << NL "  " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4(o_color[gl_VertexID]) + "
3089 			   << TypePrefix<T>() << "vec4" << expected_value << ";";
3090 		}
3091 		else if (stage == 4)
3092 		{ // CS
3093 			os << NL "  " << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>()
3094 			   << "vec4(o_color[gl_GlobalInvocationID.x]) + " << TypePrefix<T>() << "vec4" << expected_value << ";";
3095 		}
3096 
3097 		os << NL "  int g_index[6] = int[](o_color[0].x, o_color[0].y, o_color[0].z, o_color[0].w, o_color[1].r, "
3098 				 "o_color[1].g);";
3099 		if (stage == 0)
3100 		{ // VS
3101 			os << NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
3102 		}
3103 		else if (stage == 4)
3104 		{ // CS
3105 			os << NL "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
3106 		}
3107 		os << NL "  vec4 r = vec4(0.0, 1.0, 0.0, 1.0);" NL "  " << TypePrefix<T>()
3108 		   << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
3109 			  "  if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 2.0);" NL
3110 			  "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
3111 			  "  if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 3.0);" NL
3112 			  "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
3113 			  "  if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 6.0);" NL
3114 			  "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
3115 			  "  if (v != g_value) r = vec4(1.0, 0.0, float(coord.x), 23.0);" NL "  o_color[coord.x] = ivec4(r);" NL
3116 			  "}";
3117 		return os.str();
3118 	}
3119 
3120 protected:
RunStage(int stage)3121 	long RunStage(int stage)
3122 	{
3123 		m_stage = stage;
3124 		if (!AreOutputsAvailable(5))
3125 			return NOT_SUPPORTED;
3126 
3127 		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
3128 			return ERROR;
3129 		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
3130 			return ERROR;
3131 		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
3132 			return ERROR;
3133 
3134 		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3135 			return ERROR;
3136 		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
3137 			return ERROR;
3138 		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3139 			return ERROR;
3140 		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3141 			return ERROR;
3142 
3143 		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3144 			return ERROR;
3145 		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
3146 			return ERROR;
3147 		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3148 			return ERROR;
3149 		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
3150 			return ERROR;
3151 
3152 		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
3153 			return ERROR;
3154 
3155 		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
3156 			return ERROR;
3157 
3158 		return NO_ERROR;
3159 	}
3160 };
3161 
3162 //-----------------------------------------------------------------------------
3163 // AtomicMachine
3164 //-----------------------------------------------------------------------------
3165 class AtomicMachine : public ShaderImageLoadStoreBase
3166 {
3167 	GLuint m_vao;
3168 	GLuint m_buffer;
3169 
Setup()3170 	virtual long Setup()
3171 	{
3172 		glEnable(GL_RASTERIZER_DISCARD);
3173 		glGenVertexArrays(1, &m_vao);
3174 		glGenBuffers(1, &m_buffer);
3175 		return NO_ERROR;
3176 	}
3177 
Cleanup()3178 	virtual long Cleanup()
3179 	{
3180 		glDisable(GL_RASTERIZER_DISCARD);
3181 		glDeleteVertexArrays(1, &m_vao);
3182 		glDeleteBuffers(1, &m_buffer);
3183 		return NO_ERROR;
3184 	}
3185 
3186 	template <typename T>
Atomic(int target,int stage,GLenum internalformat)3187 	bool Atomic(int target, int stage, GLenum internalformat)
3188 	{
3189 		GLuint program = 0;
3190 		if (stage == 0)
3191 		{ // VS
3192 			const char* src_fs = NL "void main() {" NL "  discard;" NL "}";
3193 			program			   = BuildProgram(GenShader<T>(target, stage, internalformat).c_str(), src_fs, true, false);
3194 		}
3195 		else if (stage == 4)
3196 		{ // CS
3197 			program = CreateComputeProgram(GenShader<T>(target, stage, internalformat), true);
3198 		}
3199 
3200 		const GLenum targets[] = { GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY };
3201 		const int	kTargets  = sizeof(targets) / sizeof(targets[0]);
3202 		const int	kSize	 = 100;
3203 
3204 		GLuint textures[kTargets];
3205 		glGenTextures(kTargets, textures);
3206 
3207 		for (int i = 0; i < kTargets; ++i)
3208 		{
3209 			glBindTexture(targets[i], textures[i]);
3210 			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3211 			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3212 			if (targets[i] == GL_TEXTURE_2D)
3213 			{
3214 				glTexStorage2D(targets[i], 1, internalformat, kSize, 1);
3215 			}
3216 			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3217 			{
3218 				glTexStorage3D(targets[i], 1, internalformat, kSize, 1, 2);
3219 			}
3220 			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3221 			{
3222 				glTexStorage2D(targets[i], 1, internalformat, kSize, kSize);
3223 			}
3224 		}
3225 		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat); // 2D
3226 		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // 3D
3227 		glBindImageTexture(0, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // Cube
3228 		glBindImageTexture(3, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);  // 2DArray
3229 
3230 		std::vector<ivec4> b_data(kSize);
3231 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3232 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * 4 * 4, &b_data[0], GL_STATIC_DRAW);
3233 
3234 		glUseProgram(program);
3235 		glBindVertexArray(m_vao);
3236 		if (stage == 0)
3237 		{ // VS
3238 			glDrawArrays(GL_POINTS, 0, kSize);
3239 		}
3240 		else if (stage == 4)
3241 		{ // CS
3242 			glDispatchCompute(1, 1, 1);
3243 		}
3244 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3245 
3246 		bool   status   = true;
3247 		ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * 4 * 4, GL_MAP_READ_BIT);
3248 		for (int i = 0; i < kSize; ++i)
3249 		{
3250 			if (!Equal(out_data[i], ivec4(0, 1, 0, 1), 0))
3251 			{
3252 				status = false;
3253 				m_context.getTestContext().getLog()
3254 					<< tcu::TestLog::Message << "[" << i << "] Atomic operation check failed. ("
3255 					<< ToString(out_data[i]).c_str() << ")" << tcu::TestLog::EndMessage;
3256 			}
3257 		}
3258 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3259 		glUseProgram(0);
3260 		glDeleteProgram(program);
3261 		glDeleteTextures(kTargets, textures);
3262 		return status;
3263 	}
3264 
3265 	template <typename T>
GenShader(int target,int stage,GLenum internalformat)3266 	std::string GenShader(int target, int stage, GLenum internalformat)
3267 	{
3268 		std::ostringstream os;
3269 		os << NL "#define KSIZE 100";
3270 		if (stage == 4)
3271 		{ // CS
3272 			os << NL "layout(local_size_x = KSIZE) in;";
3273 		}
3274 		switch (target)
3275 		{
3276 		case T2D:
3277 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 1) coherent uniform "
3278 			   << TypePrefix<T>() << "image2D g_image_2d;";
3279 			break;
3280 		case T3D:
3281 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 2) coherent uniform "
3282 			   << TypePrefix<T>() << "image3D g_image_3d;";
3283 			break;
3284 		case TCM:
3285 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 0) coherent uniform "
3286 			   << TypePrefix<T>() << "imageCube g_image_cube;";
3287 			break;
3288 		case T2DA:
3289 			os << NL "layout(" << FormatEnumToString(internalformat) << ", binding = 3) coherent uniform "
3290 			   << TypePrefix<T>() << "image2DArray g_image_2darray;";
3291 			break;
3292 		}
3293 		os << NL "layout(std430) buffer out_data {" NL "  ivec4 o_color[KSIZE];" NL "} r;" NL << TypePrefix<T>()
3294 		   << "vec2 t(int i) {" NL "  return " << TypePrefix<T>()
3295 		   << "vec2(i);" NL "}" NL "void main() {" NL "  int g_value[6] = int[](r.o_color[0].x, r.o_color[0].y+1, "
3296 			  "r.o_color[0].z+2, r.o_color[0].w+3, r.o_color[1].r+4, "
3297 			  "r.o_color[1].g+5);";
3298 		if (stage == 0)
3299 		{ // VS
3300 			os << NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
3301 		}
3302 		else if (stage == 4)
3303 		{ // CS
3304 			os << NL "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
3305 		}
3306 		os << NL "  ivec4 o_color = ivec4(0, 1, 0, 1);";
3307 
3308 		switch (target)
3309 		{
3310 		case T2D:
3311 			os << NL "  ivec4 i = ivec4(1, 0, 0, 2);" NL "  imageAtomicExchange(g_image_2d, coord, t(0).x);" NL
3312 					 "  if (imageAtomicAdd(g_image_2d, coord, t(2).x) != t(0).x) o_color = i;" NL
3313 					 "  if (imageAtomicMin(g_image_2d, coord, t(3).x) != t(2).x) o_color = i;" NL
3314 					 "  if (imageAtomicMax(g_image_2d, coord, t(4).x) != t(2).x) o_color = i;" NL
3315 					 "  if (imageAtomicAnd(g_image_2d, coord, t(0).x) != t(4).x) o_color = i;" NL
3316 					 "  if (imageAtomicOr(g_image_2d, coord, t(7).x) != t(0).x) o_color = i;" NL
3317 					 "  if (imageAtomicXor(g_image_2d, coord, t(4).x) != t(7).x) o_color = i;" NL
3318 					 "  if (imageAtomicExchange(g_image_2d, coord, t(1).x) != t(3).x) o_color = i;" NL
3319 					 "  if (imageAtomicCompSwap(g_image_2d, coord, t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3320 					 "  if (imageAtomicExchange(g_image_2d, coord, t(0).x) != t(6).x) o_color = i;";
3321 			break;
3322 		case T3D:
3323 			os << NL "  ivec4 i = ivec4(1, 0, 0, 3);" NL
3324 					 "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x);" NL
3325 					 "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL
3326 					 "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3327 					 "  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), t(4).x) != t(2).x) o_color = i;" NL
3328 					 "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3329 					 "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3330 					 "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL
3331 					 "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3332 					 "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3333 					 "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3334 			break;
3335 		case TCM:
3336 			os << NL
3337 				"  ivec4 i = ivec4(1, 0, 0, 6);" NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x);" NL
3338 				"  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), t(g_value[2]).x) != t(0).x) o_color = i;" NL
3339 				"  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3340 				"  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL
3341 				"  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3342 				"  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3343 				"  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), t(4).x) != t(7).x) o_color = i;" NL
3344 				"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3345 				"  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), t(1).x, t(6).x) != t(1).x) o_color "
3346 				"= i;" NL "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3347 			break;
3348 		case T2DA:
3349 			os << NL
3350 				"  ivec4 i = ivec4(1, 0, 0, 23);" NL
3351 				"  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x);" NL
3352 				"  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), t(2).x) != t(0).x) o_color = i;" NL
3353 				"  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), t(3).x) != t(2).x) o_color = i;" NL
3354 				"  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), t(4).x) != t(2).x) o_color = i;" NL
3355 				"  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), t(0).x) != t(4).x) o_color = i;" NL
3356 				"  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), t(7).x) != t(0).x) o_color = i;" NL
3357 				"  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), t(g_value[4]).x) != t(7).x) o_color = i;" NL
3358 				"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(1).x) != t(3).x) o_color = i;" NL
3359 				"  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), t(1).x, t(6).x) != t(1).x) o_color = i;" NL
3360 				"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), t(0).x) != t(6).x) o_color = i;";
3361 			break;
3362 		}
3363 		os << NL "  r.o_color[coord.x] = o_color;" NL "}";
3364 		return os.str();
3365 	}
3366 
3367 protected:
RunStage(int stage)3368 	long RunStage(int stage)
3369 	{
3370 		if (!IsImageAtomicSupported())
3371 			return NOT_SUPPORTED;
3372 		if (!Atomic<GLint>(T2D, stage, GL_R32I))
3373 			return ERROR;
3374 		if (!Atomic<GLuint>(T2D, stage, GL_R32UI))
3375 			return ERROR;
3376 		if (!Atomic<GLint>(T3D, stage, GL_R32I))
3377 			return ERROR;
3378 		if (!Atomic<GLuint>(T3D, stage, GL_R32UI))
3379 			return ERROR;
3380 		if (!Atomic<GLint>(TCM, stage, GL_R32I))
3381 			return ERROR;
3382 		if (!Atomic<GLuint>(TCM, stage, GL_R32UI))
3383 			return ERROR;
3384 		if (!Atomic<GLint>(T2DA, stage, GL_R32I))
3385 			return ERROR;
3386 		if (!Atomic<GLuint>(T2DA, stage, GL_R32UI))
3387 			return ERROR;
3388 		return NO_ERROR;
3389 	}
3390 };
3391 
3392 //-----------------------------------------------------------------------------
3393 // 1.3.4 BasicAllTargetsLoadStoreVS
3394 //-----------------------------------------------------------------------------
3395 class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
3396 {
Run()3397 	virtual long Run()
3398 	{
3399 		if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1))
3400 			return NOT_SUPPORTED;
3401 		return RunStage(0);
3402 	}
3403 };
3404 
3405 //-----------------------------------------------------------------------------
3406 // 1.3.8 BasicAllTargetsLoadStoreCS
3407 //-----------------------------------------------------------------------------
3408 class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
3409 {
Run()3410 	virtual long Run()
3411 	{
3412 		return RunStage(4);
3413 	}
3414 };
3415 
3416 //-----------------------------------------------------------------------------
3417 // 1.3.9 BasicAllTargetsAtomicVS
3418 //-----------------------------------------------------------------------------
3419 class BasicAllTargetsAtomicVS : public AtomicMachine
3420 {
Run()3421 	virtual long Run()
3422 	{
3423 		if (!IsVSFSAvailable(4, 0) || !IsSSBInVSFSAvailable(1))
3424 			return NOT_SUPPORTED;
3425 		return RunStage(0);
3426 	}
3427 };
3428 
3429 //-----------------------------------------------------------------------------
3430 // 1.3.13 BasicAllTargetsAtomicCS
3431 //-----------------------------------------------------------------------------
3432 class BasicAllTargetsAtomicCS : public AtomicMachine
3433 {
Run()3434 	virtual long Run()
3435 	{
3436 		return RunStage(4);
3437 	}
3438 };
3439 
3440 //-----------------------------------------------------------------------------
3441 // 1.4.1 BasicGLSLMisc
3442 //-----------------------------------------------------------------------------
3443 class BasicGLSLMiscFS : public ShaderImageLoadStoreBase
3444 {
3445 	GLuint m_texture;
3446 	GLuint m_program;
3447 	GLuint m_vao, m_vbo;
3448 	GLuint m_buffer;
3449 
Setup()3450 	virtual long Setup()
3451 	{
3452 		m_texture = 0;
3453 		m_program = 0;
3454 		m_vao = m_vbo = 0;
3455 		m_buffer	  = 0;
3456 		return NO_ERROR;
3457 	}
3458 
Run()3459 	virtual long Run()
3460 	{
3461 		if (!IsVSFSAvailable(0, 2) || !IsSSBInVSFSAvailable(1))
3462 			return NOT_SUPPORTED;
3463 
3464 		const int		   kSize = 32;
3465 		std::vector<float> data(kSize * kSize * 4);
3466 
3467 		glGenTextures(1, &m_texture);
3468 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
3469 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3470 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3471 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4);
3472 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]);
3473 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3474 
3475 		const char* src_vs =
3476 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
3477 
3478 		const char* src_fs =
3479 			NL "#define KSIZE 32" NL "layout(std430) buffer out_data {" NL "  ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
3480 			   "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL
3481 			   "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
3482 			   "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image_layer0, coord, vec4(1.0));" NL
3483 			   "  memoryBarrier();" NL "  imageStore(g_image_layer1, coord, vec4(2.0));" NL "  memoryBarrier();" NL
3484 			   "  imageStore(g_image_layer0, coord, vec4(3.0));" NL "  memoryBarrier();" NL
3485 			   "  int coordIndex = coord.x + KSIZE * coord.y;" NL
3486 			   "  o_color[coordIndex] = ivec4(imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord));" NL
3487 			   "}";
3488 		m_program = BuildProgram(src_vs, src_fs);
3489 
3490 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3491 
3492 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
3493 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
3494 
3495 		glClear(GL_COLOR_BUFFER_BIT);
3496 		glViewport(0, 0, kSize, kSize);
3497 
3498 		std::vector<ivec4> o_data(kSize * kSize);
3499 		glGenBuffers(1, &m_buffer);
3500 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3501 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
3502 
3503 		glUseProgram(m_program);
3504 		glBindVertexArray(m_vao);
3505 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3506 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3507 
3508 		bool status = true;
3509 
3510 		ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3511 		for (int i = 0; i < kSize * kSize; ++i)
3512 		{
3513 			if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0))
3514 			{
3515 				status = false;
3516 				m_context.getTestContext().getLog()
3517 					<< tcu::TestLog::Message << "[" << i
3518 					<< "] Check failed. Received: " << ToString(out_data[i]).c_str()
3519 					<< " instead of: " << ToString(ivec4(5, 0, 0, 2)).c_str() << tcu::TestLog::EndMessage;
3520 			}
3521 		}
3522 
3523 		if (status)
3524 			return NO_ERROR;
3525 		else
3526 			return ERROR;
3527 	}
3528 
Cleanup()3529 	virtual long Cleanup()
3530 	{
3531 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3532 		glDeleteTextures(1, &m_texture);
3533 		glDeleteVertexArrays(1, &m_vao);
3534 		glDeleteBuffers(1, &m_vbo);
3535 		glDeleteBuffers(1, &m_buffer);
3536 		glUseProgram(0);
3537 		glDeleteProgram(m_program);
3538 		return NO_ERROR;
3539 	}
3540 };
3541 
3542 class BasicGLSLMiscCS : public ShaderImageLoadStoreBase
3543 {
3544 	GLuint m_texture;
3545 	GLuint m_program;
3546 	GLuint m_buffer;
3547 
Setup()3548 	virtual long Setup()
3549 	{
3550 		m_texture = 0;
3551 		m_program = 0;
3552 		m_buffer  = 0;
3553 		return NO_ERROR;
3554 	}
3555 
Run()3556 	virtual long Run()
3557 	{
3558 		const int		   kSize = 10;
3559 		std::vector<float> data(kSize * kSize * 4);
3560 
3561 		glGenTextures(1, &m_texture);
3562 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
3563 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3564 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3565 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, kSize, kSize, 4);
3566 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, kSize, kSize, 4, GL_RED, GL_FLOAT, &data[0]);
3567 		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3568 
3569 		const char* src_cs =
3570 			NL "#define KSIZE 10" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
3571 			   "layout(std430) buffer out_data {" NL "  ivec4 o_color[KSIZE*KSIZE];" NL "};" NL
3572 			   "layout(r32f, binding = 0) coherent restrict uniform image2D g_image_layer0;" NL
3573 			   "layout(r32f, binding = 1) volatile uniform image2D g_image_layer1;" NL "void main() {" NL
3574 			   "  ivec2 coord = ivec2(gl_LocalInvocationID.xy);" NL "  imageStore(g_image_layer0, coord, vec4(1.0));" NL
3575 			   "  memoryBarrier();" NL "  imageStore(g_image_layer1, coord, vec4(2.0));" NL "  memoryBarrier();" NL
3576 			   "  imageStore(g_image_layer0, coord, vec4(3.0));" NL "  memoryBarrier();" NL
3577 			   "  o_color[gl_LocalInvocationIndex] = ivec4(imageLoad(g_image_layer0, coord) + "
3578 			   "imageLoad(g_image_layer1, coord));" NL "}";
3579 		m_program = CreateComputeProgram(src_cs);
3580 
3581 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
3582 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_R32F);
3583 
3584 		std::vector<ivec4> o_data(kSize * kSize);
3585 		glGenBuffers(1, &m_buffer);
3586 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3587 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &o_data[0], GL_STATIC_DRAW);
3588 
3589 		glUseProgram(m_program);
3590 		glDispatchCompute(1, 1, 1);
3591 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3592 
3593 		bool status = true;
3594 
3595 		ivec4* out_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3596 		for (int i = 0; i < kSize * kSize; ++i)
3597 		{
3598 			if (!Equal(out_data[i], ivec4(5, 0, 0, 2), 0))
3599 			{
3600 				status = false;
3601 				m_context.getTestContext().getLog()
3602 					<< tcu::TestLog::Message << "[" << i
3603 					<< "] Check failed. Received: " << ToString(out_data[i]).c_str()
3604 					<< " instead of: " << ToString(ivec4(5, 0, 0, 2)).c_str() << tcu::TestLog::EndMessage;
3605 			}
3606 		}
3607 
3608 		if (status)
3609 			return NO_ERROR;
3610 		else
3611 			return ERROR;
3612 	}
3613 
Cleanup()3614 	virtual long Cleanup()
3615 	{
3616 		glDeleteTextures(1, &m_texture);
3617 		glUseProgram(0);
3618 		glDeleteProgram(m_program);
3619 		glDeleteBuffers(1, &m_buffer);
3620 		return NO_ERROR;
3621 	}
3622 };
3623 
3624 //-----------------------------------------------------------------------------
3625 // 1.4.2 BasicGLSLEarlyFragTests
3626 //-----------------------------------------------------------------------------
3627 class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
3628 {
3629 	GLuint m_texture[2];
3630 	GLuint m_program[2];
3631 	GLuint m_vao, m_vbo;
3632 	GLuint c_program;
3633 	GLuint m_buffer;
3634 
Setup()3635 	virtual long Setup()
3636 	{
3637 		m_texture[0] = m_texture[1] = 0;
3638 		m_program[0] = m_program[1] = 0;
3639 		m_vao = m_vbo = 0;
3640 		m_buffer	  = 0;
3641 		c_program	 = 0;
3642 		return NO_ERROR;
3643 	}
3644 
Run()3645 	virtual long Run()
3646 	{
3647 		if (!IsVSFSAvailable(0, 1))
3648 			return NOT_SUPPORTED;
3649 
3650 		const int		  kSize = 8;
3651 		std::vector<vec4> data(kSize * kSize);
3652 
3653 		glGenTextures(2, m_texture);
3654 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
3655 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3656 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3657 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
3658 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
3659 		glBindTexture(GL_TEXTURE_2D, 0);
3660 
3661 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
3662 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3663 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3664 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
3665 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
3666 		glBindTexture(GL_TEXTURE_2D, 0);
3667 
3668 		const char* glsl_vs =
3669 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
3670 		const char* glsl_early_frag_tests_fs =
3671 			NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
3672 			   "layout(rgba32f, binding = 0) writeonly coherent uniform image2D g_image;" NL "void main() {" NL
3673 			   "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(17.0));" NL
3674 			   "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3675 		const char* glsl_fs =
3676 			NL "layout(location = 0) out vec4 o_color;" NL
3677 			   "layout(rgba32f, binding = 1) writeonly coherent uniform image2D g_image;" NL "void main() {" NL
3678 			   "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(13.0));" NL
3679 			   "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3680 		m_program[0] = BuildProgram(glsl_vs, glsl_early_frag_tests_fs);
3681 		m_program[1] = BuildProgram(glsl_vs, glsl_fs);
3682 
3683 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3684 
3685 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3686 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3687 
3688 		glViewport(0, 0, kSize, kSize);
3689 		glBindVertexArray(m_vao);
3690 
3691 		glEnable(GL_DEPTH_TEST);
3692 		glClearColor(0.0, 1.0f, 0.0, 1.0f);
3693 		glClearDepthf(0.0f);
3694 
3695 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3696 		glUseProgram(m_program[0]);
3697 
3698 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3699 
3700 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3701 		glUseProgram(m_program[1]);
3702 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3703 
3704 		const char* check_cs =
3705 			NL "#define KSIZE 8" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
3706 			   "uniform sampler2D g_sampler;" NL "layout(std430) buffer OutputBuffer {" NL
3707 			   "  vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL
3708 			   "  data[gl_LocalInvocationIndex] = texelFetch(g_sampler, ivec2(gl_LocalInvocationID), 0);" NL "}";
3709 
3710 		c_program = CreateComputeProgram(check_cs);
3711 		std::vector<vec4> out_data(kSize * kSize);
3712 		glGenBuffers(1, &m_buffer);
3713 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3714 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
3715 
3716 		glActiveTexture(GL_TEXTURE5);
3717 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
3718 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3719 
3720 		glUseProgram(c_program);
3721 		glUniform1i(glGetUniformLocation(c_program, "g_sampler"), 5);
3722 		glDispatchCompute(1, 1, 1);
3723 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3724 		vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3725 
3726 		float					 expectedVal  = 0.0f;
3727 		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
3728 		if (renderTarget.getDepthBits() == 0)
3729 		{
3730 			expectedVal = 17.0f;
3731 		}
3732 
3733 		if (!CompareValues(map_data, kSize, vec4(expectedVal)))
3734 			return ERROR;
3735 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3736 
3737 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
3738 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
3739 
3740 		glDispatchCompute(1, 1, 1);
3741 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3742 		map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3743 
3744 		if (!CompareValues(map_data, kSize, vec4(13.0f)))
3745 			return ERROR;
3746 
3747 		return NO_ERROR;
3748 	}
3749 
Cleanup()3750 	virtual long Cleanup()
3751 	{
3752 		glDisable(GL_DEPTH_TEST);
3753 		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
3754 		glClearDepthf(1.0f);
3755 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3756 		glDeleteTextures(2, m_texture);
3757 		glDeleteVertexArrays(1, &m_vao);
3758 		glDeleteBuffers(1, &m_vbo);
3759 		glUseProgram(0);
3760 		glDeleteProgram(m_program[0]);
3761 		glDeleteProgram(m_program[1]);
3762 		glDeleteProgram(c_program);
3763 		glDeleteBuffers(1, &m_buffer);
3764 		glActiveTexture(GL_TEXTURE0);
3765 		return NO_ERROR;
3766 	}
3767 };
3768 
3769 //-----------------------------------------------------------------------------
3770 // 1.4.3 BasicGLSLConst
3771 //-----------------------------------------------------------------------------
3772 class BasicGLSLConst : public ShaderImageLoadStoreBase
3773 {
3774 	GLuint m_program;
3775 	GLuint m_buffer;
3776 
Setup()3777 	virtual long Setup()
3778 	{
3779 		m_program = 0;
3780 		m_buffer  = 0;
3781 		return NO_ERROR;
3782 	}
3783 
Run()3784 	virtual long Run()
3785 	{
3786 		const char* src_cs =
3787 			NL "layout (local_size_x = 1) in;" NL "layout(std430) buffer out_data {" NL "  ivec4 o_color;" NL "};" NL
3788 			   "uniform int MaxImageUnits;" NL "uniform int MaxCombinedShaderOutputResources;" NL
3789 			   "uniform int MaxVertexImageUniforms;" NL "uniform int MaxFragmentImageUniforms;" NL
3790 			   "uniform int MaxComputeImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL "void main() {" NL
3791 			   "  o_color = ivec4(0, 1, 0, 1);" NL
3792 			   "  if (gl_MaxImageUnits != MaxImageUnits) o_color = ivec4(1, 0, 0, 1);" NL
3793 			   "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = ivec4(1, 0, "
3794 			   "0, 2);" NL "  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = ivec4(1, 0, 0, 4);" NL
3795 			   "  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = ivec4(1, 0, 0, 5);" NL
3796 			   "  if (gl_MaxComputeImageUniforms != MaxComputeImageUniforms) o_color = ivec4(1, 0, 0, 6);" NL
3797 			   "  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = ivec4(1, 0, 0, 9);" NL "}";
3798 		m_program = CreateComputeProgram(src_cs);
3799 		glUseProgram(m_program);
3800 
3801 		GLint i;
3802 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
3803 		glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
3804 
3805 		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
3806 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
3807 
3808 		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
3809 		glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
3810 
3811 		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
3812 		glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
3813 
3814 		glGetIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &i);
3815 		glUniform1i(glGetUniformLocation(m_program, "MaxComputeImageUniforms"), i);
3816 
3817 		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
3818 		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
3819 
3820 		std::vector<ivec4> out_data(1);
3821 		glGenBuffers(1, &m_buffer);
3822 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3823 		glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4, &out_data[0], GL_STATIC_DRAW);
3824 
3825 		glDispatchCompute(1, 1, 1);
3826 
3827 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3828 		ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4, GL_MAP_READ_BIT);
3829 
3830 		if (!Equal(map_data[0], ivec4(0, 1, 0, 1), 0))
3831 		{
3832 			m_context.getTestContext().getLog()
3833 				<< tcu::TestLog::Message << "[" << i << "] Value is: " << ToString(map_data[0]).c_str()
3834 				<< ". Value should be: " << ToString(ivec4(0, 1, 0, 1)).c_str() << tcu::TestLog::EndMessage;
3835 			return ERROR;
3836 		}
3837 		return NO_ERROR;
3838 	}
3839 
Cleanup()3840 	virtual long Cleanup()
3841 	{
3842 		glUseProgram(0);
3843 		glDeleteProgram(m_program);
3844 		glDeleteBuffers(1, &m_buffer);
3845 		return NO_ERROR;
3846 	}
3847 };
3848 
3849 //-----------------------------------------------------------------------------
3850 // 2.1.1 AdvancedSyncImageAccess
3851 //-----------------------------------------------------------------------------
3852 class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
3853 {
3854 	GLuint m_buffer;
3855 	GLuint m_texture;
3856 	GLuint m_store_program;
3857 	GLuint m_draw_program;
3858 	GLuint m_attribless_vao;
3859 
Setup()3860 	virtual long Setup()
3861 	{
3862 		m_buffer		 = 0;
3863 		m_texture		 = 0;
3864 		m_store_program  = 0;
3865 		m_draw_program   = 0;
3866 		m_attribless_vao = 0;
3867 		return NO_ERROR;
3868 	}
3869 
Run()3870 	virtual long Run()
3871 	{
3872 		if (!IsVSFSAvailable(1, 0) || !IsSSBInVSFSAvailable(1))
3873 			return NOT_SUPPORTED;
3874 
3875 		const int		  kSize = 44;
3876 		const char* const glsl_store_vs =
3877 			NL "layout(rgba32f) writeonly uniform image2D g_output_data;" NL "void main() {" NL
3878 			   "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
3879 			   "  imageStore(g_output_data, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL
3880 			   "  gl_PointSize = 1.0;" NL "}";
3881 		const char* const glsl_store_fs = NL "void main() {" NL "  discard;" NL "}";
3882 		const char* const glsl_draw_vs =
3883 			NL "out vec4 vs_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL
3884 			   "uniform sampler2D g_sampler;" NL "void main() {" NL
3885 			   "  vec4 pi = imageLoad(g_image, ivec2(gl_VertexID, 0));" NL
3886 			   "  vec4 ps = texelFetch(g_sampler, ivec2(gl_VertexID, 0), 0);" NL
3887 			   "  if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3888 			   "  else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  gl_Position = pi;" NL "}";
3889 		const char* const glsl_draw_fs =
3890 			NL "#define KSIZE 44" NL "in vec4 vs_color;" NL "layout(std430) buffer OutputBuffer {" NL
3891 			   "  vec4 o_color[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3892 			   "  int coordIndex = coord.x + KSIZE * coord.y;" NL "  o_color[coordIndex] = vs_color;" NL "}";
3893 		m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs);
3894 		m_draw_program  = BuildProgram(glsl_draw_vs, glsl_draw_fs);
3895 
3896 		glGenVertexArrays(1, &m_attribless_vao);
3897 		glBindVertexArray(m_attribless_vao);
3898 
3899 		glGenTextures(1, &m_texture);
3900 		glBindTexture(GL_TEXTURE_2D, m_texture);
3901 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3902 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3903 		std::vector<ivec4> data(4);
3904 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
3905 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT, &data[0]);
3906 
3907 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
3908 
3909 		glUseProgram(m_store_program);
3910 		glDrawArrays(GL_POINTS, 0, 4);
3911 
3912 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
3913 
3914 		glViewport(0, 0, kSize, kSize);
3915 		glClear(GL_COLOR_BUFFER_BIT);
3916 		glUseProgram(m_draw_program);
3917 
3918 		std::vector<vec4> out_data(kSize * kSize);
3919 		glGenBuffers(1, &m_buffer);
3920 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3921 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &out_data[0], GL_STATIC_DRAW);
3922 
3923 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3924 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3925 		vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
3926 
3927 		if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1)))
3928 			return ERROR;
3929 
3930 		return NO_ERROR;
3931 	}
3932 
Cleanup()3933 	virtual long Cleanup()
3934 	{
3935 		glUseProgram(0);
3936 		glDeleteBuffers(1, &m_buffer);
3937 		glDeleteTextures(1, &m_texture);
3938 		glDeleteProgram(m_store_program);
3939 		glDeleteProgram(m_draw_program);
3940 		glDeleteVertexArrays(1, &m_attribless_vao);
3941 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3942 		return NO_ERROR;
3943 	}
3944 };
3945 
3946 //-----------------------------------------------------------------------------
3947 // 2.1.2 AdvancedSyncVertexArray
3948 //-----------------------------------------------------------------------------
3949 class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
3950 {
3951 	GLuint m_position_buffer;
3952 	GLuint m_color_buffer;
3953 	GLuint m_element_buffer;
3954 	GLuint m_texture[3];
3955 	GLuint m_store_program;
3956 	GLuint m_copy_program;
3957 	GLuint m_draw_program;
3958 	GLuint m_attribless_vao;
3959 	GLuint m_draw_vao;
3960 
Setup()3961 	virtual long Setup()
3962 	{
3963 		m_position_buffer = 0;
3964 		m_color_buffer	= 0;
3965 		m_element_buffer  = 0;
3966 		m_store_program   = 0;
3967 		m_draw_program	= 0;
3968 		m_copy_program	= 0;
3969 		m_attribless_vao  = 0;
3970 		m_draw_vao		  = 0;
3971 		return NO_ERROR;
3972 	}
3973 
Run()3974 	virtual long Run()
3975 	{
3976 		if (!IsVSFSAvailable(3, 0))
3977 			return NOT_SUPPORTED;
3978 		const char* const glsl_store_vs =
3979 			NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_position_buffer;" NL
3980 			   "layout(rgba32f, binding = 1) writeonly uniform image2D g_color_buffer;" NL
3981 			   "layout(r32ui, binding = 2) writeonly uniform uimage2D g_element_buffer;" NL "uniform vec4 g_color;" NL
3982 			   "void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
3983 			   "  imageStore(g_position_buffer, ivec2(gl_VertexID,0), vec4(data[gl_VertexID], 0.0, 1.0));" NL
3984 			   "  imageStore(g_color_buffer, ivec2(gl_VertexID,0), g_color);" NL
3985 			   "  imageStore(g_element_buffer, ivec2(gl_VertexID,0), uvec4(gl_VertexID));" NL "}";
3986 		const char* const glsl_store_fs = NL "void main() {" NL "  discard;" NL "}";
3987 		const char*		  glsl_copy_cs =
3988 			NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL
3989 			   "layout(rgba32f, binding = 0) readonly uniform image2D g_position_img;" NL
3990 			   "layout(rgba32f, binding = 1) readonly uniform image2D g_color_img;" NL
3991 			   "layout(r32ui, binding = 2) readonly uniform uimage2D g_element_img;" NL
3992 			   "layout(std430, binding = 1) buffer g_position_buf {" NL "  vec2 g_pos[KSIZE];" NL "};" NL
3993 			   "layout(std430, binding = 2) buffer g_color_buf {" NL "  vec4 g_col[KSIZE];" NL "};" NL
3994 			   "layout(std430, binding = 3) buffer g_element_buf {" NL "  uint g_elem[KSIZE];" NL "};" NL
3995 			   "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID.x, 0);" NL
3996 			   "  g_pos[coord.x] = (imageLoad(g_position_img, coord)).xy;" NL
3997 			   "  g_col[coord.x] = imageLoad(g_color_img, coord);" NL
3998 			   "  g_elem[coord.x] = uint((imageLoad(g_element_img, coord)).x);" NL "}";
3999 		const char* const glsl_draw_vs = NL
4000 			"layout(location = 0) in vec4 i_position;" NL "layout(location = 1) in vec4 i_color;" NL
4001 			"out vec4 vs_color;" NL "void main() {" NL "  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
4002 		const char* const glsl_draw_fs = NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
4003 											"void main() {" NL "  o_color = vs_color;" NL "}";
4004 		m_store_program = BuildProgram(glsl_store_vs, glsl_store_fs);
4005 		m_copy_program  = CreateComputeProgram(glsl_copy_cs);
4006 		m_draw_program  = BuildProgram(glsl_draw_vs, glsl_draw_fs);
4007 
4008 		glGenTextures(3, m_texture);
4009 		std::vector<ivec4> data(4);
4010 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4011 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
4012 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4013 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4014 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4015 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 4, 1);
4016 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4017 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4018 		glBindTexture(GL_TEXTURE_2D, m_texture[2]);
4019 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 1);
4020 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4021 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4022 
4023 		glGenVertexArrays(1, &m_attribless_vao);
4024 		glGenVertexArrays(1, &m_draw_vao);
4025 		glBindVertexArray(m_draw_vao);
4026 		glGenBuffers(1, &m_position_buffer);
4027 		glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
4028 		glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4029 		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
4030 		glGenBuffers(1, &m_color_buffer);
4031 		glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
4032 		glBufferData(GL_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4033 		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
4034 		glBindBuffer(GL_ARRAY_BUFFER, 0);
4035 		glEnableVertexAttribArray(0);
4036 		glEnableVertexAttribArray(1);
4037 		glGenBuffers(1, &m_element_buffer);
4038 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
4039 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * 4 * 4, 0, GL_STATIC_DRAW);
4040 		glBindVertexArray(0);
4041 
4042 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4043 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4044 		glBindImageTexture(2, m_texture[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4045 		glUseProgram(m_store_program);
4046 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
4047 		glBindVertexArray(m_attribless_vao);
4048 		glDrawArrays(GL_POINTS, 0, 4);
4049 
4050 		glUseProgram(m_copy_program);
4051 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_position_buffer);
4052 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_color_buffer);
4053 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, m_element_buffer);
4054 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4055 		glDispatchCompute(1, 1, 1);
4056 
4057 		glClear(GL_COLOR_BUFFER_BIT);
4058 		glUseProgram(m_draw_program);
4059 		glBindVertexArray(m_draw_vao);
4060 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
4061 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
4062 
4063 		if (!CheckFB(vec4(0, 1, 0, 1)))
4064 		{
4065 			return ERROR;
4066 		}
4067 
4068 		glUseProgram(m_store_program);
4069 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
4070 		glBindVertexArray(m_attribless_vao);
4071 		glDrawArrays(GL_POINTS, 0, 4);
4072 		glUseProgram(m_copy_program);
4073 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4074 		glDispatchCompute(1, 1, 1);
4075 		glClear(GL_COLOR_BUFFER_BIT);
4076 		glUseProgram(m_draw_program);
4077 		glBindVertexArray(m_draw_vao);
4078 		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
4079 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
4080 
4081 		if (!CheckFB(vec4(0, 0, 1, 1)))
4082 		{
4083 			return ERROR;
4084 		}
4085 		return NO_ERROR;
4086 	}
4087 
Cleanup()4088 	virtual long Cleanup()
4089 	{
4090 		glDisable(GL_RASTERIZER_DISCARD);
4091 		glUseProgram(0);
4092 		glDeleteTextures(3, m_texture);
4093 		glDeleteBuffers(1, &m_position_buffer);
4094 		glDeleteBuffers(1, &m_color_buffer);
4095 		glDeleteBuffers(1, &m_element_buffer);
4096 		glDeleteProgram(m_store_program);
4097 		glDeleteProgram(m_copy_program);
4098 		glDeleteProgram(m_draw_program);
4099 		glDeleteVertexArrays(1, &m_attribless_vao);
4100 		glDeleteVertexArrays(1, &m_draw_vao);
4101 		return NO_ERROR;
4102 	}
4103 };
4104 
4105 //-----------------------------------------------------------------------------
4106 // 2.1.6 AdvancedSyncImageAccess2
4107 //-----------------------------------------------------------------------------
4108 class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
4109 {
4110 	GLuint m_texture;
4111 	GLuint m_store_program;
4112 	GLuint m_draw_program;
4113 	GLuint m_vao;
4114 	GLuint m_vbo;
4115 	GLuint m_buffer;
4116 
Setup()4117 	virtual long Setup()
4118 	{
4119 		m_texture		= 0;
4120 		m_store_program = 0;
4121 		m_draw_program  = 0;
4122 		m_vao			= 0;
4123 		m_vbo			= 0;
4124 		m_buffer		= 0;
4125 		return NO_ERROR;
4126 	}
4127 
Run()4128 	virtual long Run()
4129 	{
4130 		const int kSize = 32;
4131 		if (!IsVSFSAvailable(0, 1) || !IsSSBInVSFSAvailable(1))
4132 			return NOT_SUPPORTED;
4133 		const char* const glsl_vs =
4134 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
4135 		const char* const glsl_store_fs =
4136 			NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
4137 			   "  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
4138 		const char* const glsl_draw_fs =
4139 			NL "layout(location = 0) out vec4 o_color;" NL "uniform sampler2D g_sampler;" NL
4140 			   "layout(std430) buffer OutputBuffer {" NL "  uvec4 counter;" NL "  vec4 data[];" NL "};" NL
4141 			   "void main() {" NL "  uint idx = atomicAdd(counter[0], 1u);" NL
4142 			   "  data[idx] = texelFetch(g_sampler, ivec2(gl_FragCoord.xy), 0);" NL "}";
4143 		m_store_program = BuildProgram(glsl_vs, glsl_store_fs);
4144 		m_draw_program  = BuildProgram(glsl_vs, glsl_draw_fs);
4145 
4146 		glGenTextures(1, &m_texture);
4147 		glBindTexture(GL_TEXTURE_2D, m_texture);
4148 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4149 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4150 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight());
4151 		glBindTexture(GL_TEXTURE_2D, 0);
4152 
4153 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4154 
4155 		glViewport(0, 0, kSize, kSize);
4156 		std::vector<vec4> data_b(kSize * kSize + 1);
4157 		glGenBuffers(1, &m_buffer);
4158 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4159 		glBufferData(GL_SHADER_STORAGE_BUFFER, (kSize * kSize + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4160 
4161 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4162 		glUseProgram(m_store_program);
4163 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
4164 		glBindVertexArray(m_vao);
4165 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4166 
4167 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4168 
4169 		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
4170 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4171 
4172 		glBindTexture(GL_TEXTURE_2D, m_texture);
4173 		glUseProgram(m_draw_program);
4174 		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
4175 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4176 
4177 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4178 		vec4* map_data =
4179 			(vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4180 
4181 		if (!CompareValues(map_data, kSize, vec4(0, 1, 0, 1)))
4182 			return ERROR;
4183 		return NO_ERROR;
4184 	}
4185 
Cleanup()4186 	virtual long Cleanup()
4187 	{
4188 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4189 		glUseProgram(0);
4190 		glDeleteBuffers(1, &m_vbo);
4191 		glDeleteTextures(1, &m_texture);
4192 		glDeleteProgram(m_store_program);
4193 		glDeleteProgram(m_draw_program);
4194 		glDeleteVertexArrays(1, &m_vao);
4195 		glDeleteBuffers(1, &m_buffer);
4196 		return NO_ERROR;
4197 	}
4198 };
4199 
4200 //-----------------------------------------------------------------------------
4201 // 2.2.1 AdvancedAllStagesOneImage
4202 //-----------------------------------------------------------------------------
4203 class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
4204 {
4205 	GLuint m_program;
4206 	GLuint c_program;
4207 	GLuint m_vao;
4208 	GLuint m_vbo;
4209 	GLuint m_buffer;
4210 	GLuint m_texture;
4211 
Setup()4212 	virtual long Setup()
4213 	{
4214 		m_program = 0;
4215 		c_program = 0;
4216 		m_vao	 = 0;
4217 		m_vbo	 = 0;
4218 		m_buffer  = 0;
4219 		m_texture = 0;
4220 		return NO_ERROR;
4221 	}
4222 
Run()4223 	virtual long Run()
4224 	{
4225 		const int kSize = 64;
4226 		if (!IsVSFSAvailable(1, 1) || !IsImageAtomicSupported())
4227 			return NOT_SUPPORTED;
4228 		const char* const glsl_vs =
4229 			NL "layout(location = 0) in vec4 i_position;" NL
4230 			   "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL "void main() {" NL
4231 			   "  gl_Position = i_position;" NL "  imageAtomicAdd(g_image, ivec2(0, gl_VertexID), 100u);" NL "}";
4232 		const char* const glsl_fs =
4233 			NL "#define KSIZE 64" NL "layout(r32ui, binding = 3) coherent uniform uimage2D g_image;" NL
4234 			   "void main() {" NL "  imageAtomicAdd(g_image, ivec2(0, int(gl_FragCoord.x) & 0x03), 0x1u);" NL "}";
4235 		m_program = BuildProgram(glsl_vs, glsl_fs, true, true);
4236 		const char* const glsl_cs =
4237 			NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE) in;" NL
4238 			   "layout(r32ui, binding = 3) uniform uimage2D g_image;" NL "layout(std430) buffer out_data {" NL
4239 			   "  uvec4 data[KSIZE];" NL "};" NL "void main() {" NL
4240 			   "  uvec4 v = imageLoad(g_image, ivec2(0, gl_LocalInvocationID.x));" NL
4241 			   "  data[gl_LocalInvocationIndex] = v;" NL "}";
4242 		c_program = CreateComputeProgram(glsl_cs, true);
4243 		glUseProgram(m_program);
4244 
4245 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4246 
4247 		std::vector<uvec4> ui32(16);
4248 		glGenTextures(1, &m_texture);
4249 		glBindTexture(GL_TEXTURE_2D, m_texture);
4250 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32UI, 4, 4);
4251 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4252 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4253 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32[0]);
4254 		glBindTexture(GL_TEXTURE_2D, 0);
4255 
4256 		glBindImageTexture(3, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4257 
4258 		glViewport(0, 0, kSize, kSize);
4259 		glBindVertexArray(m_vao);
4260 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4261 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4262 
4263 		std::vector<vec4> data_b(4);
4264 		glGenBuffers(1, &m_buffer);
4265 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4266 		glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4267 		glUseProgram(c_program);
4268 		glDispatchCompute(1, 1, 1);
4269 
4270 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4271 		uvec4* map_data = (uvec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * 4 * 4, GL_MAP_READ_BIT);
4272 
4273 		if (!CompareValues(map_data, 2, uvec4(1024 + 100, 0, 0, 1)))
4274 			return ERROR;
4275 		return NO_ERROR;
4276 	}
4277 
Cleanup()4278 	virtual long Cleanup()
4279 	{
4280 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4281 		glUseProgram(0);
4282 		glDeleteBuffers(1, &m_buffer);
4283 		glDeleteBuffers(1, &m_vbo);
4284 		glDeleteTextures(1, &m_texture);
4285 		glDeleteProgram(m_program);
4286 		glDeleteProgram(c_program);
4287 		glDeleteVertexArrays(1, &m_vao);
4288 		return NO_ERROR;
4289 	}
4290 };
4291 
4292 //-----------------------------------------------------------------------------
4293 // 2.3.2 AdvancedMemoryOrder
4294 //-----------------------------------------------------------------------------
4295 class AdvancedMemoryOrderVSFS : public ShaderImageLoadStoreBase
4296 {
4297 	GLuint m_buffer;
4298 	GLuint m_texture[2];
4299 	GLuint m_program;
4300 	GLuint m_vao;
4301 	GLuint m_vbo;
4302 
Setup()4303 	virtual long Setup()
4304 	{
4305 		m_buffer  = 0;
4306 		m_program = 0;
4307 		m_vao	 = 0;
4308 		m_vbo	 = 0;
4309 		return NO_ERROR;
4310 	}
4311 
Run()4312 	virtual long Run()
4313 	{
4314 		const int kSize = 11;
4315 		if (!IsVSFSAvailable(1, 1) || !IsSSBInVSFSAvailable(1))
4316 			return NOT_SUPPORTED;
4317 		const char* const glsl_vs = NL
4318 			"layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
4319 			"layout(r32f, binding = 0) uniform image2D g_image_vs;" NL "void main() {" NL
4320 			"  gl_Position = i_position;" NL "  vs_color = vec4(41, 42, 43, 44);" NL
4321 			"  imageStore(g_image_vs, ivec2(gl_VertexID), vec4(1.0));" NL
4322 			"  imageStore(g_image_vs, ivec2(gl_VertexID), vec4(2.0));" NL
4323 			"  imageStore(g_image_vs, ivec2(gl_VertexID), vec4(3.0));" NL
4324 			"  if (imageLoad(g_image_vs, ivec2(gl_VertexID)) != vec4(3,0,0,1)) vs_color = vec4(21, 22, 23, 24);" NL "}";
4325 		const char* const glsl_fs =
4326 			NL "#define KSIZE 11" NL "in vec4 vs_color;" NL "layout(r32f, binding = 1) uniform image2D g_image;" NL
4327 			   "layout(std430) buffer out_data {" NL "  vec4 data[KSIZE*KSIZE*4];" NL "};" NL "void main() {" NL
4328 			   "  ivec2 coord = ivec2(gl_FragCoord);" NL "  int coordIndex = coord.x + KSIZE * coord.y;" NL
4329 			   "  for (int i = 0; i < 4; ++i) {" NL "    data[coordIndex + i * KSIZE*KSIZE] = vs_color;" NL "  }" NL
4330 			   "  for (int i = 0; i < 4; ++i) {" NL "    imageStore(g_image, coord, vec4(i+50));" NL
4331 			   "    vec4 v = imageLoad(g_image, coord);" NL "    if (v.x != float(i+50)) {" NL
4332 			   "      data[coordIndex + i * KSIZE*KSIZE] = vec4(v.xyz, i+10);" NL "      break;" NL "    }" NL "  }" NL
4333 			   "}";
4334 		m_program = BuildProgram(glsl_vs, glsl_fs);
4335 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4336 
4337 		std::vector<float> data(kSize * kSize);
4338 		glGenTextures(2, m_texture);
4339 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4340 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4341 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4342 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4343 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]);
4344 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4345 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, kSize, kSize);
4346 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4347 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4348 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RED, GL_FLOAT, &data[0]);
4349 		glBindTexture(GL_TEXTURE_2D, 0);
4350 
4351 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4352 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
4353 
4354 		std::vector<vec4> data_b(kSize * kSize * 4);
4355 		glGenBuffers(1, &m_buffer);
4356 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4357 		glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4358 
4359 		glUseProgram(m_program);
4360 		glViewport(0, 0, kSize, kSize);
4361 		glBindVertexArray(m_vao);
4362 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4363 
4364 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4365 		vec4* map_data =
4366 			(vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4367 
4368 		if (!CompareValues(map_data, kSize * 2, vec4(41, 42, 43, 44)))
4369 			return ERROR;
4370 		return NO_ERROR;
4371 	}
4372 
Cleanup()4373 	virtual long Cleanup()
4374 	{
4375 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4376 		glUseProgram(0);
4377 		glDeleteBuffers(1, &m_vbo);
4378 		glDeleteBuffers(1, &m_buffer);
4379 		glDeleteTextures(2, m_texture);
4380 		glDeleteProgram(m_program);
4381 		glDeleteVertexArrays(1, &m_vao);
4382 		return NO_ERROR;
4383 	}
4384 };
4385 
4386 //-----------------------------------------------------------------------------
4387 // 2.4.1 AdvancedSSOSimple
4388 //-----------------------------------------------------------------------------
4389 class AdvancedSSOSimple : public ShaderImageLoadStoreBase
4390 {
4391 	bool   pipeline;
4392 	GLuint m_texture;
4393 	GLuint m_pipeline[2];
4394 	GLuint m_vsp, m_fsp0, m_fsp1;
4395 	GLuint m_vao, m_vbo;
4396 	GLuint m_program[2];
4397 	GLuint c_program;
4398 	GLuint m_buffer;
4399 
Setup()4400 	virtual long Setup()
4401 	{
4402 		c_program = 0;
4403 		m_buffer  = 0;
4404 		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4405 		glGenTextures(1, &m_texture);
4406 		const char* const glsl_vs =
4407 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
4408 		const char* const glsl_fs0 =
4409 			NL "layout(rgba32f, binding = 2) writeonly uniform image2D g_image[2];" NL "void main() {" NL
4410 			   "  int i = g_image.length();" NL "  imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+98));" NL
4411 			   "  imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+99));" NL "  discard;" NL "}";
4412 		const char* const glsl_fs1 =
4413 			NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[2];" NL "void main() {" NL
4414 			   "  int i = g_image.length();" NL "  imageStore(g_image[0], ivec2(gl_FragCoord), vec4(i+8));" NL
4415 			   "  imageStore(g_image[1], ivec2(gl_FragCoord), vec4(i+9));" NL "  discard;" NL "}";
4416 		if (pipeline)
4417 		{
4418 			glGenProgramPipelines(2, m_pipeline);
4419 			m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
4420 			m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
4421 			m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
4422 		}
4423 		else
4424 		{
4425 			m_program[0] = BuildProgram(glsl_vs, glsl_fs0);
4426 			m_program[1] = BuildProgram(glsl_vs, glsl_fs1);
4427 		}
4428 		return NO_ERROR;
4429 	}
4430 
Run()4431 	virtual long Run()
4432 	{
4433 		if (!IsVSFSAvailable(0, 2))
4434 			return NOT_SUPPORTED;
4435 		const int kSize = 4;
4436 
4437 		if (pipeline)
4438 		{
4439 			glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
4440 			glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
4441 			glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
4442 			glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
4443 		}
4444 		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4445 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4446 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4447 		glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8);
4448 
4449 		glBindImageTexture(0, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
4450 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
4451 		glBindImageTexture(2, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
4452 		glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
4453 
4454 		glBindVertexArray(m_vao);
4455 		if (pipeline)
4456 			glBindProgramPipeline(m_pipeline[0]);
4457 		else
4458 			glUseProgram(m_program[0]);
4459 		glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 1);
4460 
4461 		if (pipeline)
4462 			glBindProgramPipeline(m_pipeline[1]);
4463 		else
4464 			glUseProgram(m_program[1]);
4465 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4466 
4467 		const char* const glsl_cs =
4468 			NL "#define KSIZE 4" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4469 			   "layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL
4470 			   "layout(std430) buffer OutputBuffer {" NL "  uvec4 counter;" NL "  vec4 data[];" NL "};" NL
4471 			   "void main() {" NL "  uint idx = atomicAdd(counter[0], 1u);" NL
4472 			   "  data[idx][0] = (imageLoad(g_image[0], ivec2(gl_GlobalInvocationID))).z;" NL
4473 			   "  data[idx][1] = (imageLoad(g_image[1], ivec2(gl_GlobalInvocationID))).z;" NL
4474 			   "  data[idx][2] = (imageLoad(g_image[2], ivec2(gl_GlobalInvocationID))).z;" NL
4475 			   "  data[idx][3] = (imageLoad(g_image[3], ivec2(gl_GlobalInvocationID))).z;" NL "}";
4476 		c_program = CreateComputeProgram(glsl_cs);
4477 		glUseProgram(c_program);
4478 		int wsx   = (getWindowWidth() / kSize) * kSize;
4479 		int wsy   = (getWindowHeight() / kSize) * kSize;
4480 		int minor = wsx > wsy ? wsy : wsx;
4481 
4482 		std::vector<vec4> data_b(wsx * wsy + 1);
4483 		glGenBuffers(1, &m_buffer);
4484 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4485 		glBufferData(GL_SHADER_STORAGE_BUFFER, (wsx * wsy + 1) * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4486 
4487 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4488 		glDispatchCompute(wsx / kSize, wsy / kSize, 1);
4489 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4490 		vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 4 * 4, wsx * wsy * 4 * 4, GL_MAP_READ_BIT);
4491 
4492 		if (!CompareValues(map_data, minor, vec4(10, 11, 100, 101)))
4493 			return ERROR;
4494 		return NO_ERROR;
4495 	}
4496 
Cleanup()4497 	virtual long Cleanup()
4498 	{
4499 		glUseProgram(0);
4500 		glDeleteBuffers(1, &m_vbo);
4501 		glDeleteTextures(1, &m_texture);
4502 		if (pipeline)
4503 		{
4504 			glDeleteProgram(m_vsp);
4505 			glDeleteProgram(m_fsp0);
4506 			glDeleteProgram(m_fsp1);
4507 			glDeleteProgramPipelines(2, m_pipeline);
4508 		}
4509 		else
4510 		{
4511 			glDeleteProgram(m_program[0]);
4512 			glDeleteProgram(m_program[1]);
4513 		}
4514 		glDeleteProgram(c_program);
4515 		glDeleteVertexArrays(1, &m_vao);
4516 		glDeleteBuffers(1, &m_buffer);
4517 		return NO_ERROR;
4518 	}
4519 
4520 public:
AdvancedSSOSimple()4521 	AdvancedSSOSimple() : pipeline(true)
4522 	{
4523 	}
4524 };
4525 
4526 //-----------------------------------------------------------------------------
4527 // 2.5 AdvancedCopyImage
4528 //-----------------------------------------------------------------------------
4529 class AdvancedCopyImageFS : public ShaderImageLoadStoreBase
4530 {
4531 	GLuint m_texture[2];
4532 	GLuint m_program;
4533 	GLuint c_program;
4534 	GLuint m_vao, m_vbo, m_ebo;
4535 	GLuint m_buffer;
4536 
Setup()4537 	virtual long Setup()
4538 	{
4539 		glGenTextures(2, m_texture);
4540 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4541 		glGenBuffers(1, &m_buffer);
4542 
4543 		const char* const glsl_vs =
4544 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
4545 		const char* const glsl_fs =
4546 			NL "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL
4547 			   "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL
4548 			   "  ivec2 coord = ivec2(gl_FragCoord);" NL
4549 			   "  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
4550 		m_program				  = BuildProgram(glsl_vs, glsl_fs);
4551 		const char* const glsl_cs = NL
4552 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4553 			"layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL
4554 			"  vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4555 			"  data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}";
4556 		c_program = CreateComputeProgram(glsl_cs);
4557 
4558 		return NO_ERROR;
4559 	}
4560 
Run()4561 	virtual long Run()
4562 	{
4563 		const int kSize = 11;
4564 		if (!IsVSFSAvailable(0, 2))
4565 			return NOT_SUPPORTED;
4566 
4567 		std::vector<vec4> data(kSize * kSize, vec4(7.0f));
4568 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4569 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4570 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4571 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4572 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
4573 
4574 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4575 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4576 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4577 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4578 
4579 		glBindTexture(GL_TEXTURE_2D, 0);
4580 
4581 		glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4582 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4583 		glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4584 
4585 		std::vector<vec4> data_b(kSize * kSize);
4586 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4587 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4588 
4589 		glUseProgram(m_program);
4590 		glBindVertexArray(m_vao);
4591 		glViewport(0, 0, kSize, kSize);
4592 		glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1);
4593 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4594 
4595 		glUseProgram(c_program);
4596 		glDispatchCompute(1, 1, 1);
4597 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4598 		vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4599 
4600 		if (!CompareValues(map_data, kSize, vec4(7.f)))
4601 			return ERROR;
4602 		return NO_ERROR;
4603 	}
4604 
Cleanup()4605 	virtual long Cleanup()
4606 	{
4607 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4608 		glUseProgram(0);
4609 		glDeleteBuffers(1, &m_vbo);
4610 		glDeleteBuffers(1, &m_ebo);
4611 		glDeleteBuffers(1, &m_buffer);
4612 		glDeleteTextures(2, m_texture);
4613 		glDeleteProgram(m_program);
4614 		glDeleteProgram(c_program);
4615 		glDeleteVertexArrays(1, &m_vao);
4616 		return NO_ERROR;
4617 	}
4618 };
4619 
4620 class AdvancedCopyImageCS : public ShaderImageLoadStoreBase
4621 {
4622 	GLuint m_texture[2];
4623 	GLuint m_program;
4624 	GLuint c_program;
4625 	GLuint m_buffer;
4626 
Setup()4627 	virtual long Setup()
4628 	{
4629 		glGenTextures(2, m_texture);
4630 		glGenBuffers(1, &m_buffer);
4631 
4632 		const char* const glsl_cs =
4633 			NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4634 			   "layout(rgba32f, binding = 3) readonly uniform image2D g_input_image;" NL
4635 			   "layout(rgba32f, binding = 1) writeonly uniform image2D g_output_image;" NL "void main() {" NL
4636 			   "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4637 			   "  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "}";
4638 		m_program					= CreateComputeProgram(glsl_cs);
4639 		const char* const glsl_cs_c = NL
4640 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4641 			"layout(rgba32f, binding = 2) readonly uniform image2D g_image;" NL "layout(std430) buffer out_data {" NL
4642 			"  vec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4643 			"  data[gl_LocalInvocationIndex] = imageLoad(g_image, coord);" NL "}";
4644 		c_program = CreateComputeProgram(glsl_cs_c);
4645 
4646 		return NO_ERROR;
4647 	}
4648 
Run()4649 	virtual long Run()
4650 	{
4651 		const int kSize = 11;
4652 
4653 		std::vector<vec4> data(kSize * kSize, vec4(7.0f));
4654 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4655 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4656 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4657 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4658 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_FLOAT, &data[0]);
4659 
4660 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4661 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, kSize, kSize);
4662 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4663 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4664 
4665 		glBindTexture(GL_TEXTURE_2D, 0);
4666 
4667 		glBindImageTexture(3, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4668 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4669 		glBindImageTexture(2, m_texture[1], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
4670 
4671 		std::vector<vec4> data_b(kSize * kSize);
4672 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4673 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data_b[0], GL_STATIC_DRAW);
4674 
4675 		glUseProgram(m_program);
4676 		glDispatchCompute(1, 1, 1);
4677 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4678 
4679 		glUseProgram(c_program);
4680 		glDispatchCompute(1, 1, 1);
4681 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4682 		vec4* map_data = (vec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4683 
4684 		if (!CompareValues(map_data, kSize, vec4(7.f)))
4685 			return ERROR;
4686 		return NO_ERROR;
4687 	}
4688 
Cleanup()4689 	virtual long Cleanup()
4690 	{
4691 		glUseProgram(0);
4692 		glDeleteBuffers(1, &m_buffer);
4693 		glDeleteTextures(2, m_texture);
4694 		glDeleteProgram(m_program);
4695 		glDeleteProgram(c_program);
4696 		return NO_ERROR;
4697 	}
4698 };
4699 
4700 //-----------------------------------------------------------------------------
4701 // 2.6 AdvancedAllMips
4702 //-----------------------------------------------------------------------------
4703 class AdvancedAllMipsFS : public ShaderImageLoadStoreBase
4704 {
4705 	GLuint m_texture;
4706 	GLuint m_store_program, m_load_program;
4707 	GLuint m_vao, m_vbo, m_ebo;
4708 	GLuint m_buffer;
4709 
Setup()4710 	virtual long Setup()
4711 	{
4712 		glGenTextures(1, &m_texture);
4713 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4714 		glGenBuffers(1, &m_buffer);
4715 
4716 		const char* const glsl_vs =
4717 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
4718 		const char* const glsl_store_fs =
4719 			NL "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL
4720 			   "  imageStore(g_image[0], ivec2(gl_FragCoord), vec4(23));" NL
4721 			   "  imageStore(g_image[1], ivec2(gl_FragCoord), vec4(24));" NL
4722 			   "  imageStore(g_image[2], ivec2(gl_FragCoord), vec4(25));" NL
4723 			   "  imageStore(g_image[3], ivec2(gl_FragCoord), vec4(26));" NL "  discard;" NL "}";
4724 		const char* const glsl_load_cs = NL
4725 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4726 			"layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL
4727 			"  ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4728 			"  data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL "  vec4 c0 = imageLoad(g_image[0], coord);" NL
4729 			"  vec4 c1 = imageLoad(g_image[1], coord);" NL "  vec4 c2 = imageLoad(g_image[2], coord);" NL
4730 			"  vec4 c3 = imageLoad(g_image[3], coord);" NL
4731 			"  if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && "
4732 			"c0.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][0] = int(c0.x);" NL
4733 			"  if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && "
4734 			"c1.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][1] = int(c1.x);" NL
4735 			"  if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && "
4736 			"c2.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][2] = int(c2.x);" NL
4737 			"  if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && "
4738 			"c3.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}";
4739 		m_store_program = BuildProgram(glsl_vs, glsl_store_fs);
4740 		m_load_program  = CreateComputeProgram(glsl_load_cs);
4741 
4742 		return NO_ERROR;
4743 	}
4744 
Run()4745 	virtual long Run()
4746 	{
4747 		const int kSize = 11;
4748 		if (!IsVSFSAvailable(0, 4))
4749 			return NOT_SUPPORTED;
4750 		glBindTexture(GL_TEXTURE_2D, m_texture);
4751 		glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128);
4752 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4753 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4754 		glBindTexture(GL_TEXTURE_2D, 0);
4755 
4756 		glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4757 		glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4758 		glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4759 		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4760 
4761 		std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4762 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4763 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4764 
4765 		glViewport(0, 0, kSize, kSize);
4766 		glBindVertexArray(m_vao);
4767 
4768 		glUseProgram(m_store_program);
4769 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
4770 
4771 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4772 
4773 		glUseProgram(m_load_program);
4774 		glDispatchCompute(1, 1, 1);
4775 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4776 		ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4777 
4778 		if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5)))
4779 			return ERROR;
4780 		return NO_ERROR;
4781 	}
4782 
Cleanup()4783 	virtual long Cleanup()
4784 	{
4785 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4786 		glUseProgram(0);
4787 		glDeleteBuffers(1, &m_vbo);
4788 		glDeleteBuffers(1, &m_ebo);
4789 		glDeleteTextures(1, &m_texture);
4790 		glDeleteProgram(m_store_program);
4791 		glDeleteProgram(m_load_program);
4792 		glDeleteVertexArrays(1, &m_vao);
4793 		glDeleteBuffers(1, &m_buffer);
4794 		return NO_ERROR;
4795 	}
4796 };
4797 
4798 class AdvancedAllMipsCS : public ShaderImageLoadStoreBase
4799 {
4800 	GLuint m_texture;
4801 	GLuint m_store_program, m_load_program;
4802 	GLuint m_buffer;
4803 
Setup()4804 	virtual long Setup()
4805 	{
4806 		glGenTextures(1, &m_texture);
4807 		glGenBuffers(1, &m_buffer);
4808 
4809 		const char* const glsl_store_cs =
4810 			NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4811 			   "layout(rgba32f, binding = 0) writeonly uniform image2D g_image[4];" NL "void main() {" NL
4812 			   "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL "  imageStore(g_image[0], coord, vec4(23));" NL
4813 			   "  imageStore(g_image[1], coord, vec4(24));" NL "  imageStore(g_image[2], coord, vec4(25));" NL
4814 			   "  imageStore(g_image[3], coord, vec4(26));" NL "}";
4815 		const char* const glsl_load_cs = NL
4816 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4817 			"layout(rgba32f, binding = 0) readonly uniform image2D g_image[4];" NL "layout(std430) buffer out_data {" NL
4818 			"  ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4819 			"  data[gl_LocalInvocationIndex] = ivec4(2, 3, 4, 5);" NL "  vec4 c0 = imageLoad(g_image[0], coord);" NL
4820 			"  vec4 c1 = imageLoad(g_image[1], coord);" NL "  vec4 c2 = imageLoad(g_image[2], coord);" NL
4821 			"  vec4 c3 = imageLoad(g_image[3], coord);" NL
4822 			"  if ((all(lessThan(coord, ivec2(2))) && c0 != vec4(23)) || (any(greaterThanEqual(coord, ivec2(2))) && "
4823 			"c0.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][0] = int(c0.x);" NL
4824 			"  if ((all(lessThan(coord, ivec2(4))) && c1 != vec4(24)) || (any(greaterThanEqual(coord, ivec2(4))) && "
4825 			"c1.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][1] = int(c1.x);" NL
4826 			"  if ((all(lessThan(coord, ivec2(8))) && c2 != vec4(25)) || (any(greaterThanEqual(coord, ivec2(8))) && "
4827 			"c2.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][2] = int(c2.x);" NL
4828 			"  if ((all(lessThan(coord, ivec2(16))) && c3 != vec4(26)) || (any(greaterThanEqual(coord, ivec2(16))) && "
4829 			"c3.xyz != vec3(0.0)))" NL "      data[gl_LocalInvocationIndex][3] = int(c3.x);" NL "}";
4830 		m_store_program = CreateComputeProgram(glsl_store_cs);
4831 		m_load_program  = CreateComputeProgram(glsl_load_cs);
4832 
4833 		return NO_ERROR;
4834 	}
4835 
Run()4836 	virtual long Run()
4837 	{
4838 		const int kSize = 11;
4839 		glBindTexture(GL_TEXTURE_2D, m_texture);
4840 		glTexStorage2D(GL_TEXTURE_2D, 8, GL_RGBA32F, 128, 128);
4841 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4842 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4843 		glBindTexture(GL_TEXTURE_2D, 0);
4844 
4845 		glBindImageTexture(0, m_texture, 6, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4846 		glBindImageTexture(1, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4847 		glBindImageTexture(2, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4848 		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4849 
4850 		std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4851 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4852 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4853 
4854 		glUseProgram(m_store_program);
4855 		glDispatchCompute(1, 1, 1);
4856 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4857 
4858 		glUseProgram(m_load_program);
4859 		glDispatchCompute(1, 1, 1);
4860 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4861 		ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4862 
4863 		if (!CompareValues(map_data, kSize, ivec4(2, 3, 4, 5)))
4864 			return ERROR;
4865 		return NO_ERROR;
4866 	}
4867 
Cleanup()4868 	virtual long Cleanup()
4869 	{
4870 		glUseProgram(0);
4871 		glDeleteTextures(1, &m_texture);
4872 		glDeleteProgram(m_store_program);
4873 		glDeleteProgram(m_load_program);
4874 		glDeleteBuffers(1, &m_buffer);
4875 		return NO_ERROR;
4876 	}
4877 };
4878 
4879 //-----------------------------------------------------------------------------
4880 // 2.7 AdvancedCast
4881 //-----------------------------------------------------------------------------
4882 class AdvancedCastFS : public ShaderImageLoadStoreBase
4883 {
4884 	GLuint m_texture[2];
4885 	GLuint m_program;
4886 	GLuint c_program;
4887 	GLuint m_vao, m_vbo, m_ebo;
4888 	GLuint m_buffer;
4889 
Setup()4890 	virtual long Setup()
4891 	{
4892 		glGenTextures(2, m_texture);
4893 		glGenBuffers(1, &m_buffer);
4894 		m_program = 0;
4895 		c_program = 0;
4896 		return NO_ERROR;
4897 	}
4898 
Run()4899 	virtual long Run()
4900 	{
4901 		if (!IsVSFSAvailable(0, 2) || !IsImageAtomicSupported())
4902 			return NOT_SUPPORTED;
4903 		const int kSize = 11;
4904 		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
4905 
4906 		const char* const glsl_vs =
4907 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
4908 		const char* const glsl_fs =
4909 			NL "#define KSIZE 11" NL "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL
4910 			   "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL
4911 			   "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageAtomicAdd(g_image0, coord, 2);" NL
4912 			   "  imageAtomicAdd(g_image0, coord, -1);" NL "  imageAtomicAdd(g_image1, coord, 1u);" NL
4913 			   "  imageAtomicAdd(g_image1, coord, 2u);" NL "}";
4914 		m_program = BuildProgram(glsl_vs, glsl_fs, false, true);
4915 
4916 		const char* const glsl_cs = NL
4917 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
4918 			"layout(r32i, binding = 0) uniform iimage2D gi_image;" NL
4919 			"layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL
4920 			"  ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
4921 			"  data[gl_LocalInvocationIndex].yx = imageLoad(gi_image, coord).xy;" NL
4922 			"  data[gl_LocalInvocationIndex].wz = ivec2(imageLoad(gu_image, coord).xz);" NL "}";
4923 		c_program = CreateComputeProgram(glsl_cs);
4924 
4925 		std::vector<GLubyte> data(kSize * kSize * 4 * 4);
4926 		glActiveTexture(GL_TEXTURE11);
4927 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4928 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4929 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
4930 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4931 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4932 		glActiveTexture(GL_TEXTURE15);
4933 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4934 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
4935 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
4936 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4937 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4938 
4939 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
4940 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
4941 
4942 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
4943 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
4944 
4945 		glUseProgram(m_program);
4946 		glBindVertexArray(m_vao);
4947 		glViewport(0, 0, kSize, kSize);
4948 		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
4949 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
4950 
4951 		glUseProgram(c_program);
4952 		glDispatchCompute(1, 1, 1);
4953 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
4954 		ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
4955 
4956 		if (!CompareValues(map_data, kSize, ivec4(0, 1, 0, 3)))
4957 			return ERROR;
4958 		return NO_ERROR;
4959 	}
4960 
Cleanup()4961 	virtual long Cleanup()
4962 	{
4963 		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4964 		glUseProgram(0);
4965 		glDeleteBuffers(1, &m_vbo);
4966 		glDeleteBuffers(1, &m_ebo);
4967 		glDeleteBuffers(1, &m_buffer);
4968 		glDeleteTextures(2, m_texture);
4969 		glDeleteProgram(m_program);
4970 		glDeleteProgram(c_program);
4971 		glDeleteVertexArrays(1, &m_vao);
4972 		glActiveTexture(GL_TEXTURE0);
4973 		return NO_ERROR;
4974 	}
4975 };
4976 
4977 class AdvancedCastCS : public ShaderImageLoadStoreBase
4978 {
4979 	GLuint m_texture[2];
4980 	GLuint m_program;
4981 	GLuint c_program;
4982 	GLuint m_buffer;
4983 
Setup()4984 	virtual long Setup()
4985 	{
4986 		glGenTextures(2, m_texture);
4987 		glGenBuffers(1, &m_buffer);
4988 		m_program = 0;
4989 		c_program = 0;
4990 		return NO_ERROR;
4991 	}
4992 
Run()4993 	virtual long Run()
4994 	{
4995 		const int kSize = 11;
4996 		if (!IsImageAtomicSupported())
4997 			return NO_ERROR;
4998 
4999 		const char* const glsl_cs =
5000 			NL "#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
5001 			   "layout(r32i, binding = 0) coherent uniform iimage2D g_image0;" NL
5002 			   "layout(r32ui, binding = 1) coherent uniform uimage2D g_image1;" NL "void main() {" NL
5003 			   "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL "  imageAtomicAdd(g_image0, coord, 222);" NL
5004 			   "  imageAtomicAdd(g_image0, coord, -11);" NL "  imageAtomicAdd(g_image1, coord, 1u);" NL
5005 			   "  imageAtomicAdd(g_image1, coord, 2u);" NL "}";
5006 		m_program = CreateComputeProgram(glsl_cs, true);
5007 
5008 		const char* const glsl_cs_c = NL
5009 			"#define KSIZE 11" NL "layout (local_size_x = KSIZE, local_size_y = KSIZE) in;" NL
5010 			"layout(r32i, binding = 0) uniform iimage2D gi_image;" NL
5011 			"layout(r32ui, binding = 1) uniform uimage2D gu_image;" NL "layout(std430) buffer out_data {" NL
5012 			"  ivec4 data[KSIZE*KSIZE];" NL "};" NL "void main() {" NL "  ivec2 coord = ivec2(gl_LocalInvocationID);" NL
5013 			"  data[gl_LocalInvocationIndex].yz = imageLoad(gi_image, coord).xw;" NL
5014 			"  data[gl_LocalInvocationIndex].wx = ivec2(imageLoad(gu_image, coord).xy);" NL "}";
5015 		c_program = CreateComputeProgram(glsl_cs_c);
5016 
5017 		std::vector<GLubyte> data(kSize * kSize * 4 * 4);
5018 		glActiveTexture(GL_TEXTURE11);
5019 		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
5020 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5021 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
5022 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5023 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5024 		glActiveTexture(GL_TEXTURE15);
5025 		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
5026 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
5027 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSize, kSize, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
5028 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5029 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5030 
5031 		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5032 		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5033 
5034 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
5035 		glBufferData(GL_SHADER_STORAGE_BUFFER, kSize * kSize * 4 * 4, &data[0], GL_STATIC_DRAW);
5036 
5037 		glUseProgram(m_program);
5038 		glDispatchCompute(1, 1, 1);
5039 		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5040 
5041 		glUseProgram(c_program);
5042 		glDispatchCompute(1, 1, 1);
5043 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5044 		ivec4* map_data = (ivec4*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, kSize * kSize * 4 * 4, GL_MAP_READ_BIT);
5045 
5046 		if (!CompareValues(map_data, kSize, ivec4(0, 211, 1, 3)))
5047 			return ERROR;
5048 		return NO_ERROR;
5049 	}
5050 
Cleanup()5051 	virtual long Cleanup()
5052 	{
5053 		glUseProgram(0);
5054 		glDeleteBuffers(1, &m_buffer);
5055 		glDeleteTextures(2, m_texture);
5056 		glDeleteProgram(m_program);
5057 		glDeleteProgram(c_program);
5058 		glActiveTexture(GL_TEXTURE0);
5059 		return NO_ERROR;
5060 	}
5061 };
5062 //-----------------------------------------------------------------------------
5063 // 4.1 NegativeUniform
5064 //-----------------------------------------------------------------------------
5065 class NegativeUniform : public ShaderImageLoadStoreBase
5066 {
5067 	GLuint m_program;
5068 
Setup()5069 	virtual long Setup()
5070 	{
5071 		m_program = 0;
5072 		return NO_ERROR;
5073 	}
5074 
Run()5075 	virtual long Run()
5076 	{
5077 		const char* glsl_vs =
5078 			NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5079 		const char* glsl_fs = NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
5080 								 "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
5081 								 "  imageStore(g_image, coord, vec4(0.0));" NL "  discard;" NL "}";
5082 		m_program = BuildProgram(glsl_vs, glsl_fs);
5083 
5084 		GLint max_image_units;
5085 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
5086 		glUseProgram(m_program);
5087 		bool  status = true;
5088 		GLint i		 = 1;
5089 		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5090 		if (glGetError() != GL_INVALID_OPERATION)
5091 			status = false;
5092 		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
5093 		if (glGetError() != GL_INVALID_OPERATION)
5094 			status = false;
5095 		glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
5096 		if (glGetError() != GL_INVALID_OPERATION)
5097 			status = false;
5098 		glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
5099 		if (glGetError() != GL_INVALID_OPERATION)
5100 			status = false;
5101 
5102 		if (!status)
5103 		{
5104 			m_context.getTestContext().getLog()
5105 				<< tcu::TestLog::Message << "glUniform* should generate INVALID_OPERATION "
5106 				<< "if the location refers to an image variable." << tcu::TestLog::EndMessage;
5107 			return ERROR;
5108 		}
5109 
5110 		glUseProgram(0);
5111 		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), 1);
5112 		if (glGetError() != GL_INVALID_OPERATION)
5113 			status = false;
5114 		glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &i);
5115 		if (glGetError() != GL_INVALID_OPERATION)
5116 			status = false;
5117 		glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
5118 		if (glGetError() != GL_INVALID_OPERATION)
5119 			status = false;
5120 		glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
5121 		if (glGetError() != GL_INVALID_OPERATION)
5122 			status = false;
5123 
5124 		if (!status)
5125 		{
5126 			m_context.getTestContext().getLog()
5127 				<< tcu::TestLog::Message << "glProgramUniform* should generate INVALID_OPERATION "
5128 				<< "if the location refers to an image variable." << tcu::TestLog::EndMessage;
5129 			return ERROR;
5130 		}
5131 
5132 		return NO_ERROR;
5133 	}
5134 
Cleanup()5135 	virtual long Cleanup()
5136 	{
5137 		glUseProgram(0);
5138 		glDeleteProgram(m_program);
5139 		return NO_ERROR;
5140 	}
5141 };
5142 
5143 //-----------------------------------------------------------------------------
5144 // 4.2 NegativeBind
5145 //-----------------------------------------------------------------------------
5146 class NegativeBind : public ShaderImageLoadStoreBase
5147 {
5148 	GLuint m_texture, m_texture2;
5149 
Setup()5150 	virtual long Setup()
5151 	{
5152 		m_texture  = 0;
5153 		m_texture2 = 0;
5154 		return NO_ERROR;
5155 	}
5156 
Run()5157 	virtual long Run()
5158 	{
5159 		GLint max_image_units;
5160 		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
5161 		glGenTextures(1, &m_texture);
5162 		glBindTexture(GL_TEXTURE_2D, m_texture);
5163 		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 64, 64);
5164 
5165 		glBindImageTexture(max_image_units, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5166 		if (glGetError() != GL_INVALID_VALUE)
5167 		{
5168 			m_context.getTestContext().getLog()
5169 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> "
5170 				<< "is greater than or equal to the value of MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
5171 			return ERROR;
5172 		}
5173 
5174 		glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5175 		if (glGetError() != GL_INVALID_VALUE)
5176 		{
5177 			m_context.getTestContext().getLog()
5178 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> "
5179 				<< "is not the name of an existing texture object." << tcu::TestLog::EndMessage;
5180 			return ERROR;
5181 		}
5182 
5183 		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
5184 		if (glGetError() != GL_INVALID_VALUE)
5185 		{
5186 			m_context.getTestContext().getLog()
5187 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <format> "
5188 				<< "is not a legal format." << tcu::TestLog::EndMessage;
5189 			return ERROR;
5190 		}
5191 
5192 		glBindImageTexture(1, m_texture, -1, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5193 		if (glGetError() != GL_INVALID_VALUE)
5194 		{
5195 			m_context.getTestContext().getLog()
5196 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <level> "
5197 				<< "is less than zero." << tcu::TestLog::EndMessage;
5198 			return ERROR;
5199 		}
5200 
5201 		glBindImageTexture(1, m_texture, 0, GL_FALSE, -1, GL_READ_ONLY, GL_RGBA32F);
5202 		if (glGetError() != GL_INVALID_VALUE)
5203 		{
5204 			m_context.getTestContext().getLog()
5205 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <layer> "
5206 				<< "is less than zero." << tcu::TestLog::EndMessage;
5207 			return ERROR;
5208 		}
5209 
5210 		glGenTextures(1, &m_texture2);
5211 		glBindTexture(GL_TEXTURE_2D, m_texture2);
5212 		glBindImageTexture(1, m_texture2, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
5213 		if (glGetError() != GL_INVALID_OPERATION)
5214 		{
5215 			m_context.getTestContext().getLog()
5216 				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> "
5217 				<< "is a mutable texture object." << tcu::TestLog::EndMessage;
5218 			return ERROR;
5219 		}
5220 
5221 		return NO_ERROR;
5222 	}
5223 
Cleanup()5224 	virtual long Cleanup()
5225 	{
5226 		glDeleteTextures(1, &m_texture);
5227 		glDeleteTextures(1, &m_texture2);
5228 		return NO_ERROR;
5229 	}
5230 };
5231 
5232 //-----------------------------------------------------------------------------
5233 // 4.3 NegativeCompileErrors
5234 //-----------------------------------------------------------------------------
5235 class NegativeCompileErrors : public ShaderImageLoadStoreBase
5236 {
Run()5237 	virtual long Run()
5238 	{
5239 		if (!Compile( // writeonly & readonly qualifiers
5240 				NL "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
5241 				   "  vec4 o_color;" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5242 			return ERROR;
5243 
5244 		if (!Compile( // writeonly && reading
5245 				NL "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5246 				   "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5247 			return ERROR;
5248 
5249 		if (!Compile( //readonly && writing
5250 				NL "uniform vec4 i_color;" NL "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
5251 				   "  vec4 o_color;" NL "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
5252 			return ERROR;
5253 
5254 		if (!Compile( // no format layout && load
5255 				NL "uniform image2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5256 				   "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5257 			return ERROR;
5258 
5259 		if (!Compile( // no fromat layout && readonly && load
5260 				NL "readonly uniform image2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5261 				   "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
5262 			return ERROR;
5263 
5264 		if (!Compile( // target type image1D not supported
5265 				NL "layout(r32i) uniform image1D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5266 				   "  o_color = vec4(1.0);" NL "}"))
5267 			return ERROR;
5268 
5269 		if (!Compile( // format layout not compatible with type
5270 				NL "layout(rgba16) writeonly uniform iimage2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5271 				   "  o_color = vec4(1.0);" NL "}"))
5272 			return ERROR;
5273 
5274 		if (!Compile( // imageAtomicAdd doesn't support r32f
5275 				NL "#extension GL_OES_shader_image_atomic : require" NL
5276 				   "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5277 				   "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
5278 			return ERROR;
5279 
5280 		if (!Compile( // imageAtomicAdd doesn't support rgba8i
5281 				NL "#extension GL_OES_shader_image_atomic : require" NL
5282 				   "layout(rgba8i) coherent uniform iimage2D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5283 				   "  imageAtomicAdd(g_image, ivec2(1), 1);" NL "  o_color = vec4(1.0);" NL "}"))
5284 			return ERROR;
5285 
5286 		if (!Compile( // format layout not compatible with type
5287 				NL "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5288 				   "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
5289 			return ERROR;
5290 
5291 		if (!Compile( // format layout not compatible with type
5292 				NL "layout(r32f) uniform uimage2DArray g_image;" NL "void main() {" NL "  vec4 o_color;" NL
5293 				   "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
5294 			return ERROR;
5295 
5296 		if (!Compile( // wrong function argument type
5297 				NL "layout(r32f) coherent uniform image2D g_image;" NL "vec4 Load(iimage2D image) {" NL
5298 				   "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  vec4 o_color;" NL
5299 				   "  o_color = Load(g_image);" NL "}"))
5300 			return ERROR;
5301 
5302 		return NO_ERROR;
5303 	}
5304 
Compile(const std::string & source)5305 	bool Compile(const std::string& source)
5306 	{
5307 		const char* const csVer  = "#version 310 es" NL "layout(local_size_x = 1) in;";
5308 		const char* const src[3] = { csVer, kGLSLPrec, source.c_str() };
5309 		const GLuint	  sh	 = glCreateShader(GL_COMPUTE_SHADER);
5310 		glShaderSource(sh, 3, src, NULL);
5311 		glCompileShader(sh);
5312 
5313 		GLchar log[1024];
5314 		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
5315 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
5316 											<< log << tcu::TestLog::EndMessage;
5317 
5318 		GLint status;
5319 		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
5320 		glDeleteShader(sh);
5321 
5322 		if (status == GL_TRUE)
5323 		{
5324 			m_context.getTestContext().getLog()
5325 				<< tcu::TestLog::Message << "Compilation should fail [compute shader]." << tcu::TestLog::EndMessage;
5326 			return false;
5327 		}
5328 		const char* const fsVer   = "#version 310 es" NL "precision highp float;";
5329 		const char* const fsrc[3] = { fsVer, kGLSLPrec, source.c_str() };
5330 		const GLuint	  fsh	 = glCreateShader(GL_FRAGMENT_SHADER);
5331 		glShaderSource(fsh, 3, fsrc, NULL);
5332 		glCompileShader(fsh);
5333 
5334 		glGetShaderInfoLog(fsh, sizeof(log), NULL, log);
5335 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
5336 											<< log << tcu::TestLog::EndMessage;
5337 		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
5338 		glDeleteShader(fsh);
5339 
5340 		if (status == GL_TRUE)
5341 		{
5342 			m_context.getTestContext().getLog()
5343 				<< tcu::TestLog::Message << "Compilation should fail [fragment shader]." << tcu::TestLog::EndMessage;
5344 			return false;
5345 		}
5346 
5347 		return true;
5348 	}
5349 };
5350 
5351 //-----------------------------------------------------------------------------
5352 // 4.4 NegativeLinkErrors
5353 //-----------------------------------------------------------------------------
5354 class NegativeLinkErrors : public ShaderImageLoadStoreBase
5355 {
Run()5356 	virtual long Run()
5357 	{
5358 		if (!IsVSFSAvailable(1, 1))
5359 			return NOT_SUPPORTED;
5360 		if (!Link(NL "layout(location = 0) in vec4 i_position;" NL
5361 					 "layout(rgba32f) writeonly uniform highp image3D g_image;" NL "void main() {" NL
5362 					 "  imageStore(g_image, ivec3(gl_VertexID), vec4(0));" NL "  gl_Position = i_position;" NL "}",
5363 
5364 				  NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL
5365 					 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5366 					 "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
5367 			return ERROR;
5368 
5369 		if (!Link(NL "layout(location = 0) in vec4 i_position;" NL
5370 					 "layout(rgba32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5371 					 "  imageStore(g_image, ivec2(gl_VertexID), vec4(0));" NL "  gl_Position = i_position;" NL "}",
5372 
5373 				  NL "precision highp float;" NL "layout(location = 0) out vec4 o_color;" NL
5374 					 "layout(r32f) writeonly uniform highp image2D g_image;" NL "void main() {" NL
5375 					 "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
5376 			return ERROR;
5377 
5378 		return NO_ERROR;
5379 	}
5380 
Link(const std::string & vs,const std::string & fs)5381 	bool Link(const std::string& vs, const std::string& fs)
5382 	{
5383 		const char* const sVer = "#version 310 es";
5384 		const GLuint	  p	= glCreateProgram();
5385 
5386 		const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
5387 		glAttachShader(p, vsh);
5388 		glDeleteShader(vsh);
5389 		const char* const vssrc[2] = { sVer, vs.c_str() };
5390 		glShaderSource(vsh, 2, vssrc, NULL);
5391 		glCompileShader(vsh);
5392 
5393 		const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
5394 		glAttachShader(p, fsh);
5395 		glDeleteShader(fsh);
5396 		const char* const fssrc[2] = { sVer, fs.c_str() };
5397 		glShaderSource(fsh, 2, fssrc, NULL);
5398 		glCompileShader(fsh);
5399 
5400 		GLint status;
5401 		glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
5402 		if (status == GL_FALSE)
5403 		{
5404 			glDeleteProgram(p);
5405 			m_context.getTestContext().getLog()
5406 				<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
5407 			return false;
5408 		}
5409 		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
5410 		if (status == GL_FALSE)
5411 		{
5412 			glDeleteProgram(p);
5413 			m_context.getTestContext().getLog()
5414 				<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
5415 			return false;
5416 		}
5417 
5418 		glLinkProgram(p);
5419 
5420 		GLchar log[1024];
5421 		glGetProgramInfoLog(p, sizeof(log), NULL, log);
5422 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
5423 											<< log << tcu::TestLog::EndMessage;
5424 
5425 		glGetProgramiv(p, GL_LINK_STATUS, &status);
5426 		glDeleteProgram(p);
5427 
5428 		if (status == GL_TRUE)
5429 		{
5430 			m_context.getTestContext().getLog()
5431 				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
5432 			return false;
5433 		}
5434 
5435 		return true;
5436 	}
5437 };
5438 
5439 } // anonymous namespace
5440 
ShaderImageLoadStoreTests(deqp::Context & context)5441 ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
5442 	: TestCaseGroup(context, "shader_image_load_store", "")
5443 {
5444 }
5445 
~ShaderImageLoadStoreTests(void)5446 ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
5447 {
5448 }
5449 
init()5450 void ShaderImageLoadStoreTests::init()
5451 {
5452 	using namespace deqp;
5453 	addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
5454 	addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
5455 	addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
5456 	addChild(new TestSubcase(m_context, "basic-api-barrier-byRegion", TestSubcase::Create<BasicAPIBarrierByRegion>));
5457 	addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
5458 	addChild(new TestSubcase(m_context, "basic-allFormats-store-fs", TestSubcase::Create<BasicAllFormatsStoreFS>));
5459 	addChild(new TestSubcase(m_context, "basic-allFormats-store-cs", TestSubcase::Create<BasicAllFormatsStoreCS>));
5460 	addChild(new TestSubcase(m_context, "basic-allFormats-load-fs", TestSubcase::Create<BasicAllFormatsLoadFS>));
5461 	addChild(new TestSubcase(m_context, "basic-allFormats-load-cs", TestSubcase::Create<BasicAllFormatsLoadCS>));
5462 	addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
5463 							 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
5464 	addChild(new TestSubcase(m_context, "basic-allTargets-store-fs", TestSubcase::Create<BasicAllTargetsStoreFS>));
5465 	addChild(new TestSubcase(m_context, "basic-allTargets-store-cs", TestSubcase::Create<BasicAllTargetsStoreCS>));
5466 	addChild(new TestSubcase(m_context, "basic-allTargets-load-fs", TestSubcase::Create<BasicAllTargetsLoadFS>));
5467 	addChild(new TestSubcase(m_context, "basic-allTargets-load-cs", TestSubcase::Create<BasicAllTargetsLoadCS>));
5468 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicFS", TestSubcase::Create<BasicAllTargetsAtomicFS>));
5469 	addChild(
5470 		new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
5471 	addChild(
5472 		new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
5473 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
5474 	addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
5475 	addChild(new TestSubcase(m_context, "basic-glsl-misc-fs", TestSubcase::Create<BasicGLSLMiscFS>));
5476 	addChild(new TestSubcase(m_context, "basic-glsl-misc-cs", TestSubcase::Create<BasicGLSLMiscCS>));
5477 	addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
5478 	addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
5479 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
5480 	addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
5481 	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
5482 	addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
5483 	addChild(new TestSubcase(m_context, "advanced-memory-order-vsfs", TestSubcase::Create<AdvancedMemoryOrderVSFS>));
5484 	addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
5485 	addChild(new TestSubcase(m_context, "advanced-copyImage-fs", TestSubcase::Create<AdvancedCopyImageFS>));
5486 	addChild(new TestSubcase(m_context, "advanced-copyImage-cs", TestSubcase::Create<AdvancedCopyImageCS>));
5487 	addChild(new TestSubcase(m_context, "advanced-allMips-fs", TestSubcase::Create<AdvancedAllMipsFS>));
5488 	addChild(new TestSubcase(m_context, "advanced-allMips-cs", TestSubcase::Create<AdvancedAllMipsCS>));
5489 	addChild(new TestSubcase(m_context, "advanced-cast-fs", TestSubcase::Create<AdvancedCastFS>));
5490 	addChild(new TestSubcase(m_context, "advanced-cast-cs", TestSubcase::Create<AdvancedCastCS>));
5491 	addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
5492 	addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
5493 	addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
5494 	addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
5495 }
5496 
5497 } // namespace es31compatibility
5498 } // namespace gl4cts
5499