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