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