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 "gl4cShaderImageLoadStoreTests.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 <climits>
32#include <cstdarg>
33#include <deque>
34#include <iomanip>
35#include <map>
36#include <sstream>
37#include <tcuFloat.hpp>
38
39namespace gl4cts
40{
41using namespace glw;
42
43namespace
44{
45typedef tcu::Vec2  vec2;
46typedef tcu::Vec4  vec4;
47typedef tcu::IVec4 ivec4;
48typedef tcu::UVec4 uvec4;
49typedef tcu::Mat4  mat4;
50
51class ShaderImageLoadStoreBase : public deqp::SubcaseBase
52{
53	virtual std::string Title()
54	{
55		return "";
56	}
57
58	virtual std::string Purpose()
59	{
60		return "";
61	}
62
63	virtual std::string Method()
64	{
65		return "";
66	}
67
68	virtual std::string PassCriteria()
69	{
70		return "";
71	}
72
73public:
74	bool SupportedInVS(int requiredVS)
75	{
76		GLint imagesVS;
77		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
78		if (imagesVS >= requiredVS)
79			return true;
80		else
81		{
82			std::ostringstream reason;
83			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
84				   << std::endl;
85			OutputNotSupported(reason.str());
86			return false;
87		}
88	}
89
90	bool SupportedInTCS(int requiredTCS)
91	{
92		GLint imagesTCS;
93		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
94		if (imagesTCS >= requiredTCS)
95			return true;
96		else
97		{
98			std::ostringstream reason;
99			reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
100				   << std::endl;
101			OutputNotSupported(reason.str());
102			return false;
103		}
104	}
105
106	bool SupportedInTES(int requiredTES)
107	{
108		GLint imagesTES;
109		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
110		if (imagesTES >= requiredTES)
111			return true;
112		else
113		{
114			std::ostringstream reason;
115			reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
116				   << std::endl;
117			OutputNotSupported(reason.str());
118			return false;
119		}
120	}
121
122	bool SupportedInGS(int requiredGS)
123	{
124		GLint imagesGS;
125		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
126		if (imagesGS >= requiredGS)
127			return true;
128		else
129		{
130			std::ostringstream reason;
131			reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
132				   << std::endl;
133			OutputNotSupported(reason.str());
134			return false;
135		}
136	}
137
138	bool SupportedInGeomStages(int required)
139	{
140		return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
141			   SupportedInGS(required);
142	}
143
144	bool SupportedInStage(int stage, int required)
145	{
146		switch (stage)
147		{
148		case 0:
149			return SupportedInVS(required);
150		case 1:
151			return SupportedInTCS(required);
152		case 2:
153			return SupportedInTES(required);
154		case 3:
155			return SupportedInGS(required);
156		default:
157			return true;
158		}
159	}
160
161	bool SupportedSamples(int required)
162	{
163		int i;
164		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
165		if (i >= required)
166			return true;
167		else
168		{
169			std::ostringstream reason;
170			reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
171			OutputNotSupported(reason.str());
172			return false;
173		}
174	}
175
176	int getWindowWidth()
177	{
178		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
179		return renderTarget.getWidth();
180	}
181
182	int getWindowHeight()
183	{
184		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
185		return renderTarget.getHeight();
186	}
187
188	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
189	{
190		if (fabs(c0[0] - c1[0]) > epsilon[0])
191			return false;
192		if (fabs(c0[1] - c1[1]) > epsilon[1])
193			return false;
194		if (fabs(c0[2] - c1[2]) > epsilon[2])
195			return false;
196		if (fabs(c0[3] - c1[3]) > epsilon[3])
197			return false;
198		return true;
199	}
200
201	bool IsEqual(vec4 a, vec4 b)
202	{
203		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
204	}
205
206	bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
207	{
208		if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
209		{
210			return ColorEqual(v0, v1, vec4(0.0001f));
211		}
212		else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
213		{
214			return ColorEqual(v0, v1, vec4(0.01f));
215		}
216		return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
217	}
218
219	bool Equal(const ivec4& a, const ivec4& b, GLenum)
220	{
221		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
222	}
223
224	bool Equal(const uvec4& a, const uvec4& b, GLenum)
225	{
226		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
227	}
228
229	template <class T>
230	std::string ToString(T v)
231	{
232		std::ostringstream s;
233		s << "[";
234		for (int i = 0; i < 4; ++i)
235			s << v[i] << (i == 3 ? "" : ",");
236		s << "]";
237		return s.str();
238	}
239
240	bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
241	{
242		bool					 status		  = true;
243		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
244		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
245		vec4					 g_color_eps  = vec4(
246			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
247			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
248
249		std::vector<vec4> fb(w * h);
250		glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
251
252		for (int yy = 0; yy < h; ++yy)
253		{
254			for (int xx = 0; xx < w; ++xx)
255			{
256				const int idx = yy * w + xx;
257				if (!ColorEqual(fb[idx], expected, g_color_eps))
258				{
259					m_context.getTestContext().getLog()
260						<< tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
261						<< tcu::TestLog::EndMessage;
262					status = false;
263					return status;
264				}
265			}
266		}
267		return status;
268	}
269
270	bool CompileShader(GLuint shader)
271	{
272		glCompileShader(shader);
273
274		GLint status;
275		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
276		if (status == GL_FALSE)
277		{
278			GLsizei length;
279			GLchar  log[1024];
280			glGetShaderInfoLog(shader, sizeof(log), &length, log);
281			if (length > 1)
282			{
283				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
284													<< log << tcu::TestLog::EndMessage;
285			}
286			return false;
287		}
288		return true;
289	}
290
291	bool LinkProgram(GLuint program)
292	{
293		glLinkProgram(program);
294
295		GLint status;
296		glGetProgramiv(program, GL_LINK_STATUS, &status);
297		if (status == GL_FALSE)
298		{
299			GLsizei length;
300			GLchar  log[1024];
301			glGetProgramInfoLog(program, sizeof(log), &length, log);
302			if (length > 1)
303			{
304				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
305													<< log << tcu::TestLog::EndMessage;
306			}
307			return false;
308		}
309		return true;
310	}
311
312	GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
313						const char* src_fs, bool* result = NULL)
314	{
315		const GLuint p = glCreateProgram();
316
317		if (src_vs)
318		{
319			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
320			glAttachShader(p, sh);
321			glDeleteShader(sh);
322			glShaderSource(sh, 1, &src_vs, NULL);
323			if (!CompileShader(sh))
324			{
325				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
326				if (result)
327					*result = false;
328				return p;
329			}
330		}
331		if (src_tcs)
332		{
333			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
334			glAttachShader(p, sh);
335			glDeleteShader(sh);
336			glShaderSource(sh, 1, &src_tcs, NULL);
337			if (!CompileShader(sh))
338			{
339				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
340				if (result)
341					*result = false;
342				return p;
343			}
344		}
345		if (src_tes)
346		{
347			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
348			glAttachShader(p, sh);
349			glDeleteShader(sh);
350			glShaderSource(sh, 1, &src_tes, NULL);
351			if (!CompileShader(sh))
352			{
353				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
354				if (result)
355					*result = false;
356				return p;
357			}
358		}
359		if (src_gs)
360		{
361			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
362			glAttachShader(p, sh);
363			glDeleteShader(sh);
364			glShaderSource(sh, 1, &src_gs, NULL);
365			if (!CompileShader(sh))
366			{
367				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
368				if (result)
369					*result = false;
370				return p;
371			}
372		}
373		if (src_fs)
374		{
375			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
376			glAttachShader(p, sh);
377			glDeleteShader(sh);
378			glShaderSource(sh, 1, &src_fs, NULL);
379			if (!CompileShader(sh))
380			{
381				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
382				if (result)
383					*result = false;
384				return p;
385			}
386		}
387		if (!LinkProgram(p))
388		{
389			if (src_vs)
390				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
391			if (src_tcs)
392				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
393			if (src_tes)
394				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
395			if (src_gs)
396				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
397			if (src_fs)
398				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
399			if (result)
400				*result = false;
401			return p;
402		}
403
404		return p;
405	}
406
407	GLuint BuildShaderProgram(GLenum type, const char* src)
408	{
409		const GLuint p = glCreateShaderProgramv(type, 1, &src);
410
411		GLint status;
412		glGetProgramiv(p, GL_LINK_STATUS, &status);
413		if (status == GL_FALSE)
414		{
415			GLchar log[1024];
416			glGetProgramInfoLog(p, sizeof(log), NULL, log);
417			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
418												<< log << "\n"
419												<< src << tcu::TestLog::EndMessage;
420		}
421
422		return p;
423	}
424
425	void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
426	{
427		assert(vao && vbo);
428
429		// interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
430		const float v[] = {
431			-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,
432			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,
433			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,
434		};
435		glGenBuffers(1, vbo);
436		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
437		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
438		glBindBuffer(GL_ARRAY_BUFFER, 0);
439
440		if (ebo)
441		{
442			std::vector<GLushort> index_data(4);
443			for (int i = 0; i < 4; ++i)
444			{
445				index_data[i] = static_cast<GLushort>(i);
446			}
447			glGenBuffers(1, ebo);
448			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
449			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
450			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
451		}
452
453		glGenVertexArrays(1, vao);
454		glBindVertexArray(*vao);
455		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
456		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
457		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
458		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
459		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
460		glBindBuffer(GL_ARRAY_BUFFER, 0);
461		glEnableVertexAttribArray(0);
462		glEnableVertexAttribArray(1);
463		glEnableVertexAttribArray(2);
464		glEnableVertexAttribArray(3);
465		if (ebo)
466		{
467			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
468		}
469		glBindVertexArray(0);
470	}
471
472	std::string FormatEnumToString(GLenum e)
473	{
474		switch (e)
475		{
476		case GL_RGBA32F:
477			return "rgba32f";
478		case GL_RGBA16F:
479			return "rgba16f";
480		case GL_RG32F:
481			return "rg32f";
482		case GL_RG16F:
483			return "rg16f";
484		case GL_R11F_G11F_B10F:
485			return "r11f_g11f_b10f";
486		case GL_R32F:
487			return "r32f";
488		case GL_R16F:
489			return "r16f";
490
491		case GL_RGBA32UI:
492			return "rgba32ui";
493		case GL_RGBA16UI:
494			return "rgba16ui";
495		case GL_RGB10_A2UI:
496			return "rgb10_a2ui";
497		case GL_RGBA8UI:
498			return "rgba8ui";
499		case GL_RG32UI:
500			return "rg32ui";
501		case GL_RG16UI:
502			return "rg16ui";
503		case GL_RG8UI:
504			return "rg8ui";
505		case GL_R32UI:
506			return "r32ui";
507		case GL_R16UI:
508			return "r16ui";
509		case GL_R8UI:
510			return "r8ui";
511
512		case GL_RGBA32I:
513			return "rgba32i";
514		case GL_RGBA16I:
515			return "rgba16i";
516		case GL_RGBA8I:
517			return "rgba8i";
518		case GL_RG32I:
519			return "rg32i";
520		case GL_RG16I:
521			return "rg16i";
522		case GL_RG8I:
523			return "rg8i";
524		case GL_R32I:
525			return "r32i";
526		case GL_R16I:
527			return "r16i";
528		case GL_R8I:
529			return "r8i";
530
531		case GL_RGBA16:
532			return "rgba16";
533		case GL_RGB10_A2:
534			return "rgb10_a2";
535		case GL_RGBA8:
536			return "rgba8";
537		case GL_RG16:
538			return "rg16";
539		case GL_RG8:
540			return "rg8";
541		case GL_R16:
542			return "r16";
543		case GL_R8:
544			return "r8";
545
546		case GL_RGBA16_SNORM:
547			return "rgba16_snorm";
548		case GL_RGBA8_SNORM:
549			return "rgba8_snorm";
550		case GL_RG16_SNORM:
551			return "rg16_snorm";
552		case GL_RG8_SNORM:
553			return "rg8_snorm";
554		case GL_R16_SNORM:
555			return "r16_snorm";
556		case GL_R8_SNORM:
557			return "r8_snorm";
558		}
559
560		assert(0);
561		return "";
562	}
563
564	const char* StageName(int stage)
565	{
566		switch (stage)
567		{
568		case 0:
569			return "Vertex Shader";
570		case 1:
571			return "Tessellation Control Shader";
572		case 2:
573			return "Tessellation Evaluation Shader";
574		case 3:
575			return "Geometry Shader";
576		case 4:
577			return "Compute Shader";
578		}
579		assert(0);
580		return NULL;
581	}
582
583	template <typename T>
584	GLenum Format();
585
586	template <typename T>
587	GLenum Type();
588
589	template <typename T>
590	std::string TypePrefix();
591
592	template <typename T>
593	GLenum ImageType(GLenum target);
594
595	void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
596	{
597		glClearBufferfv(buffer, drawbuffer, &color[0]);
598	}
599
600	void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
601	{
602		glClearBufferiv(buffer, drawbuffer, &color[0]);
603	}
604
605	void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
606	{
607		glClearBufferuiv(buffer, drawbuffer, &color[0]);
608	}
609
610	bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
611					  GLint size, GLenum type)
612	{
613		std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
614		assert(iter != name_index_map.end());
615
616		GLchar  name_gl[32];
617		GLsizei length_gl;
618		GLint   size_gl;
619		GLenum  type_gl;
620
621		glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
622
623		if (std::string(name_gl) != name)
624		{
625			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
626												<< " should be " << name << tcu::TestLog::EndMessage;
627			return false;
628		}
629		if (length_gl != static_cast<GLsizei>(name.length()))
630		{
631			m_context.getTestContext().getLog()
632				<< tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
633				<< ")" << tcu::TestLog::EndMessage;
634			return false;
635		}
636		if (size_gl != size)
637		{
638			m_context.getTestContext().getLog()
639				<< tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
640				<< ")" << tcu::TestLog::EndMessage;
641			return false;
642		}
643		if (type_gl != type)
644		{
645			m_context.getTestContext().getLog()
646				<< tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
647				<< ")" << tcu::TestLog::EndMessage;
648			return false;
649		}
650
651		return true;
652	}
653
654	bool CheckMax(GLenum pname, GLint min_value)
655	{
656		GLboolean b;
657		GLint	 i;
658		GLfloat   f;
659		GLdouble  d;
660		GLint64   i64;
661
662		glGetIntegerv(pname, &i);
663		if (i < min_value)
664			return false;
665
666		glGetBooleanv(pname, &b);
667		if (b != (i ? GL_TRUE : GL_FALSE))
668			return false;
669
670		glGetFloatv(pname, &f);
671		if (static_cast<GLint>(f) < min_value)
672			return false;
673
674		glGetDoublev(pname, &d);
675		if (static_cast<GLint>(d) < min_value)
676			return false;
677
678		glGetInteger64v(pname, &i64);
679		if (static_cast<GLint>(i64) < min_value)
680			return false;
681
682		return true;
683	}
684
685	bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
686					  GLenum format)
687	{
688		GLint	 i;
689		GLboolean b;
690
691		glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
692		if (static_cast<GLuint>(i) != texture)
693		{
694			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
695												<< " should be " << texture << tcu::TestLog::EndMessage;
696			return false;
697		}
698		glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
699		if (b != (i ? GL_TRUE : GL_FALSE))
700		{
701			m_context.getTestContext().getLog()
702				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
703				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
704			return false;
705		}
706
707		glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
708		if (i != level)
709		{
710			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
711												<< " should be " << level << tcu::TestLog::EndMessage;
712			return false;
713		}
714		glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
715		if (b != (i ? GL_TRUE : GL_FALSE))
716		{
717			m_context.getTestContext().getLog()
718				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
719				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
720			return false;
721		}
722
723		glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
724		if (i != layered)
725		{
726			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
727												<< " should be " << layered << tcu::TestLog::EndMessage;
728			return false;
729		}
730		glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
731		if (b != (i ? GL_TRUE : GL_FALSE))
732		{
733			m_context.getTestContext().getLog()
734				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
735				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
736			return false;
737		}
738
739		glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
740		if (i != layer)
741		{
742			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
743												<< " should be " << layer << tcu::TestLog::EndMessage;
744			return false;
745		}
746		glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
747		if (b != (i ? GL_TRUE : GL_FALSE))
748		{
749			m_context.getTestContext().getLog()
750				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
751				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
752			return false;
753		}
754
755		glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
756		if (static_cast<GLenum>(i) != access)
757		{
758			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
759												<< " should be " << access << tcu::TestLog::EndMessage;
760			return false;
761		}
762		glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
763		if (b != (i ? GL_TRUE : GL_FALSE))
764		{
765			m_context.getTestContext().getLog()
766				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
767				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
768			return false;
769		}
770
771		glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
772		if (static_cast<GLenum>(i) != format)
773		{
774			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
775												<< " should be " << format << tcu::TestLog::EndMessage;
776			return false;
777		}
778		glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
779		if (b != (i ? GL_TRUE : GL_FALSE))
780		{
781			m_context.getTestContext().getLog()
782				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
783				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
784			return false;
785		}
786
787		return true;
788	}
789	const char* EnumToString(GLenum e)
790	{
791		switch (e)
792		{
793		case GL_TEXTURE_1D:
794			return "GL_TEXTURE_1D";
795		case GL_TEXTURE_2D:
796			return "GL_TEXTURE_2D";
797		case GL_TEXTURE_3D:
798			return "GL_TEXTURE_3D";
799		case GL_TEXTURE_RECTANGLE:
800			return "GL_TEXTURE_RECTANGLE";
801		case GL_TEXTURE_CUBE_MAP:
802			return "GL_TEXTURE_CUBE_MAP";
803		case GL_TEXTURE_1D_ARRAY:
804			return "GL_TEXTURE_1D_ARRAY";
805		case GL_TEXTURE_2D_ARRAY:
806			return "GL_TEXTURE_2D_ARRAY";
807		case GL_TEXTURE_CUBE_MAP_ARRAY:
808			return "GL_TEXTURE_CUBE_MAP_ARRAY";
809
810		default:
811			assert(0);
812			break;
813		}
814		return NULL;
815	}
816};
817
818template <>
819GLenum ShaderImageLoadStoreBase::Format<vec4>()
820{
821	return GL_RGBA;
822}
823
824template <>
825GLenum ShaderImageLoadStoreBase::Format<ivec4>()
826{
827	return GL_RGBA_INTEGER;
828}
829
830template <>
831GLenum ShaderImageLoadStoreBase::Format<uvec4>()
832{
833	return GL_RGBA_INTEGER;
834}
835
836template <>
837GLenum ShaderImageLoadStoreBase::Format<GLint>()
838{
839	return GL_RED_INTEGER;
840}
841
842template <>
843GLenum ShaderImageLoadStoreBase::Format<GLuint>()
844{
845	return GL_RED_INTEGER;
846}
847
848template <>
849GLenum ShaderImageLoadStoreBase::Type<vec4>()
850{
851	return GL_FLOAT;
852}
853
854template <>
855GLenum ShaderImageLoadStoreBase::Type<ivec4>()
856{
857	return GL_INT;
858}
859
860template <>
861GLenum ShaderImageLoadStoreBase::Type<uvec4>()
862{
863	return GL_UNSIGNED_INT;
864}
865
866template <>
867GLenum ShaderImageLoadStoreBase::Type<GLint>()
868{
869	return GL_INT;
870}
871
872template <>
873GLenum ShaderImageLoadStoreBase::Type<GLuint>()
874{
875	return GL_UNSIGNED_INT;
876}
877
878template <>
879std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
880{
881	return "";
882}
883
884template <>
885std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
886{
887	return "i";
888}
889
890template <>
891std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
892{
893	return "u";
894}
895
896template <>
897std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
898{
899	return "i";
900}
901
902template <>
903std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
904{
905	return "u";
906}
907
908template <>
909GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
910{
911	switch (target)
912	{
913	case GL_TEXTURE_1D:
914		return GL_IMAGE_1D;
915	case GL_TEXTURE_2D:
916		return GL_IMAGE_2D;
917	case GL_TEXTURE_3D:
918		return GL_IMAGE_3D;
919	case GL_TEXTURE_RECTANGLE:
920		return GL_IMAGE_2D_RECT;
921	case GL_TEXTURE_CUBE_MAP:
922		return GL_IMAGE_CUBE;
923	case GL_TEXTURE_BUFFER:
924		return GL_IMAGE_BUFFER;
925	case GL_TEXTURE_1D_ARRAY:
926		return GL_IMAGE_1D_ARRAY;
927	case GL_TEXTURE_2D_ARRAY:
928		return GL_IMAGE_2D_ARRAY;
929	case GL_TEXTURE_CUBE_MAP_ARRAY:
930		return GL_IMAGE_CUBE_MAP_ARRAY;
931	case GL_TEXTURE_2D_MULTISAMPLE:
932		return GL_IMAGE_2D_MULTISAMPLE;
933	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
934		return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
935	}
936	assert(0);
937	return 0;
938}
939
940template <>
941GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
942{
943	switch (target)
944	{
945	case GL_TEXTURE_1D:
946		return GL_INT_IMAGE_1D;
947	case GL_TEXTURE_2D:
948		return GL_INT_IMAGE_2D;
949	case GL_TEXTURE_3D:
950		return GL_INT_IMAGE_3D;
951	case GL_TEXTURE_RECTANGLE:
952		return GL_INT_IMAGE_2D_RECT;
953	case GL_TEXTURE_CUBE_MAP:
954		return GL_INT_IMAGE_CUBE;
955	case GL_TEXTURE_BUFFER:
956		return GL_INT_IMAGE_BUFFER;
957	case GL_TEXTURE_1D_ARRAY:
958		return GL_INT_IMAGE_1D_ARRAY;
959	case GL_TEXTURE_2D_ARRAY:
960		return GL_INT_IMAGE_2D_ARRAY;
961	case GL_TEXTURE_CUBE_MAP_ARRAY:
962		return GL_INT_IMAGE_CUBE_MAP_ARRAY;
963	case GL_TEXTURE_2D_MULTISAMPLE:
964		return GL_INT_IMAGE_2D_MULTISAMPLE;
965	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
966		return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
967	}
968	assert(0);
969	return 0;
970}
971
972template <>
973GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
974{
975	switch (target)
976	{
977	case GL_TEXTURE_1D:
978		return GL_UNSIGNED_INT_IMAGE_1D;
979	case GL_TEXTURE_2D:
980		return GL_UNSIGNED_INT_IMAGE_2D;
981	case GL_TEXTURE_3D:
982		return GL_UNSIGNED_INT_IMAGE_3D;
983	case GL_TEXTURE_RECTANGLE:
984		return GL_UNSIGNED_INT_IMAGE_2D_RECT;
985	case GL_TEXTURE_CUBE_MAP:
986		return GL_UNSIGNED_INT_IMAGE_CUBE;
987	case GL_TEXTURE_BUFFER:
988		return GL_UNSIGNED_INT_IMAGE_BUFFER;
989	case GL_TEXTURE_1D_ARRAY:
990		return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
991	case GL_TEXTURE_2D_ARRAY:
992		return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
993	case GL_TEXTURE_CUBE_MAP_ARRAY:
994		return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
995	case GL_TEXTURE_2D_MULTISAMPLE:
996		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
997	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
998		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
999	}
1000	assert(0);
1001	return 0;
1002}
1003
1004//-----------------------------------------------------------------------------
1005// 1.1.1 BasicAPIGet
1006//-----------------------------------------------------------------------------
1007class BasicAPIGet : public ShaderImageLoadStoreBase
1008{
1009	virtual long Run()
1010	{
1011		if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1012		{
1013			m_context.getTestContext().getLog()
1014				<< tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1015			return ERROR;
1016		}
1017		if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1018		{
1019			m_context.getTestContext().getLog()
1020				<< tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1021				<< tcu::TestLog::EndMessage;
1022			return ERROR;
1023		}
1024		if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1025		{
1026			m_context.getTestContext().getLog()
1027				<< tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1028			return ERROR;
1029		}
1030		if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1031		{
1032			m_context.getTestContext().getLog()
1033				<< tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1034				<< tcu::TestLog::EndMessage;
1035			return ERROR;
1036		}
1037		if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1038		{
1039			m_context.getTestContext().getLog()
1040				<< tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1041				<< tcu::TestLog::EndMessage;
1042			return ERROR;
1043		}
1044		if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1045		{
1046			m_context.getTestContext().getLog()
1047				<< tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1048				<< tcu::TestLog::EndMessage;
1049			return ERROR;
1050		}
1051		if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1052		{
1053			m_context.getTestContext().getLog()
1054				<< tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1055				<< tcu::TestLog::EndMessage;
1056			return ERROR;
1057		}
1058		if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1059		{
1060			m_context.getTestContext().getLog()
1061				<< tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1062				<< tcu::TestLog::EndMessage;
1063			return ERROR;
1064		}
1065		if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1066		{
1067			m_context.getTestContext().getLog()
1068				<< tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1069				<< tcu::TestLog::EndMessage;
1070			return ERROR;
1071		}
1072		return NO_ERROR;
1073	}
1074};
1075//-----------------------------------------------------------------------------
1076// 1.1.2 BasicAPIBind
1077//-----------------------------------------------------------------------------
1078class BasicAPIBind : public ShaderImageLoadStoreBase
1079{
1080	GLuint m_texture;
1081
1082	virtual long Setup()
1083	{
1084		m_texture = 0;
1085		return NO_ERROR;
1086	}
1087
1088	virtual long Run()
1089	{
1090		for (GLuint index = 0; index < 8; ++index)
1091		{
1092			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1093			{
1094				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1095													<< " has invalid default state." << tcu::TestLog::EndMessage;
1096				return ERROR;
1097			}
1098		}
1099
1100		glGenTextures(1, &m_texture);
1101		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1102		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1103		glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1104		glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1105		glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1106		glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1107		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1108
1109		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1110		if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1111			return ERROR;
1112
1113		glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1114		if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1115			return ERROR;
1116
1117		glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1118		if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1119			return ERROR;
1120
1121		glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1122		if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1123			return ERROR;
1124
1125		glDeleteTextures(1, &m_texture);
1126		m_texture = 0;
1127
1128		for (GLuint index = 0; index < 8; ++index)
1129		{
1130			GLint name;
1131			glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1132			if (name != 0)
1133			{
1134				m_context.getTestContext().getLog()
1135					<< tcu::TestLog::Message << "Binding point " << index
1136					<< " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1137				return ERROR;
1138			}
1139		}
1140
1141		return NO_ERROR;
1142	}
1143
1144	virtual long Cleanup()
1145	{
1146		glDeleteTextures(1, &m_texture);
1147		return NO_ERROR;
1148	}
1149};
1150//-----------------------------------------------------------------------------
1151// 1.1.3 BasicAPIBarrier
1152//-----------------------------------------------------------------------------
1153class BasicAPIBarrier : public ShaderImageLoadStoreBase
1154{
1155	virtual long Run()
1156	{
1157		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1158		glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1159		glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1160		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1161		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1162		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1163		glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1164		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1165		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1166		glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1167		glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1168		glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1169
1170		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1171						GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1172						GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1173						GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1174
1175		glMemoryBarrier(GL_ALL_BARRIER_BITS);
1176
1177		return NO_ERROR;
1178	}
1179};
1180//-----------------------------------------------------------------------------
1181// 1.1.4 BasicAPITexParam
1182//-----------------------------------------------------------------------------
1183class BasicAPITexParam : public ShaderImageLoadStoreBase
1184{
1185	GLuint m_texture;
1186
1187	virtual long Setup()
1188	{
1189		m_texture = 0;
1190		return NO_ERROR;
1191	}
1192
1193	virtual long Run()
1194	{
1195		glGenTextures(1, &m_texture);
1196		glBindTexture(GL_TEXTURE_2D, m_texture);
1197		glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1198
1199		GLint   i;
1200		GLfloat f;
1201		GLuint  ui;
1202
1203		glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1204		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1205		{
1206			m_context.getTestContext().getLog()
1207				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1208				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1209				<< tcu::TestLog::EndMessage;
1210			return ERROR;
1211		}
1212		glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1213		if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1214		{
1215			m_context.getTestContext().getLog()
1216				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1217				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1218				<< tcu::TestLog::EndMessage;
1219			return ERROR;
1220		}
1221		glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1222		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1223		{
1224			m_context.getTestContext().getLog()
1225				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1226				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1227				<< tcu::TestLog::EndMessage;
1228			return ERROR;
1229		}
1230		glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1231		if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1232		{
1233			m_context.getTestContext().getLog()
1234				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1235				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1236				<< tcu::TestLog::EndMessage;
1237			return ERROR;
1238		}
1239
1240		return NO_ERROR;
1241	}
1242
1243	virtual long Cleanup()
1244	{
1245		glDeleteTextures(1, &m_texture);
1246		return NO_ERROR;
1247	}
1248};
1249//-----------------------------------------------------------------------------
1250// 1.2.1 BasicAllFormatsStore
1251//-----------------------------------------------------------------------------
1252class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1253{
1254	GLuint m_vao;
1255	GLuint m_vbo;
1256
1257	virtual long Setup()
1258	{
1259		m_vao = 0;
1260		m_vbo = 0;
1261		return NO_ERROR;
1262	}
1263
1264	virtual long Run()
1265	{
1266		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1267
1268		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1269			return ERROR;
1270		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1271			return ERROR;
1272		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1273			return ERROR;
1274
1275		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1276			return ERROR;
1277		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1278			return ERROR;
1279		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1280			return ERROR;
1281
1282		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1283			return ERROR;
1284		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1285			return ERROR;
1286		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1287			return ERROR;
1288
1289		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1290			return ERROR;
1291
1292		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1293			return ERROR;
1294		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1295			return ERROR;
1296		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1297			return ERROR;
1298
1299		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1300			return ERROR;
1301		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1302			return ERROR;
1303		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1304			return ERROR;
1305
1306		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1307			return ERROR;
1308		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1309			return ERROR;
1310		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1311			return ERROR;
1312		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1313			return ERROR;
1314
1315		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1316			return ERROR;
1317		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1318			return ERROR;
1319		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1320			return ERROR;
1321
1322		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1323			return ERROR;
1324		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1325			return ERROR;
1326		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1327			return ERROR;
1328
1329		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1330			return ERROR;
1331		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1332			return ERROR;
1333		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1334			return ERROR;
1335		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1336			return ERROR;
1337
1338		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1339			return ERROR;
1340		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1341			return ERROR;
1342		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1343			return ERROR;
1344
1345		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1346			return ERROR;
1347		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1348			return ERROR;
1349		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1350			return ERROR;
1351
1352		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1353			return ERROR;
1354		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1355			return ERROR;
1356		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1357			return ERROR;
1358
1359		return NO_ERROR;
1360	}
1361
1362	template <typename T>
1363	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1364	{
1365		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1366							 "  gl_Position = i_position;" NL "}";
1367		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1368		const int	  kSize   = 16;
1369		std::vector<T> data(kSize * kSize);
1370		GLuint		   texture;
1371		glGenTextures(1, &texture);
1372
1373		for (GLuint unit = 0; unit < 8; ++unit)
1374		{
1375			glBindTexture(GL_TEXTURE_2D, texture);
1376			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1377			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1378			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1379			glBindTexture(GL_TEXTURE_2D, 0);
1380
1381			glViewport(0, 0, kSize, kSize);
1382			glUseProgram(program);
1383			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1384			glBindVertexArray(m_vao);
1385			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1386
1387			glBindTexture(GL_TEXTURE_2D, texture);
1388			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1389			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1390
1391			for (int i = 0; i < kSize * kSize; ++i)
1392			{
1393				if (!Equal(data[i], expected_value, internalformat))
1394				{
1395					glDeleteTextures(1, &texture);
1396					glUseProgram(0);
1397					glDeleteProgram(program);
1398					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1399														<< ". Value should be: " << ToString(expected_value)
1400														<< ". Format is: " << FormatEnumToString(internalformat)
1401														<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1402					return false;
1403				}
1404			}
1405
1406			if (unit < 7)
1407			{
1408				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1409			}
1410		}
1411
1412		glDeleteTextures(1, &texture);
1413		glUseProgram(0);
1414		glDeleteProgram(program);
1415
1416		return true;
1417	}
1418
1419	virtual long Cleanup()
1420	{
1421		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1422		glDeleteVertexArrays(1, &m_vao);
1423		glDeleteBuffers(1, &m_vbo);
1424		return NO_ERROR;
1425	}
1426
1427	template <typename T>
1428	std::string GenFS(GLenum internalformat, const T& value)
1429	{
1430		std::ostringstream os;
1431		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1432		   << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1433								 "  imageStore(g_image, coord, "
1434		   << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1435		return os.str();
1436	}
1437};
1438//-----------------------------------------------------------------------------
1439// 1.2.2 BasicAllFormatsLoad
1440//-----------------------------------------------------------------------------
1441class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1442{
1443	GLuint m_vao;
1444	GLuint m_vbo;
1445
1446	virtual long Setup()
1447	{
1448		m_vao = 0;
1449		m_vbo = 0;
1450		return NO_ERROR;
1451	}
1452
1453	virtual long Run()
1454	{
1455		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1456
1457		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1458			return ERROR;
1459		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1460			return ERROR;
1461		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1462			return ERROR;
1463
1464		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1465			return ERROR;
1466		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1467			return ERROR;
1468		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1469			return ERROR;
1470
1471		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1472			return ERROR;
1473		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1474			return ERROR;
1475		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1476			return ERROR;
1477
1478		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1479			return ERROR;
1480
1481		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1482			return ERROR;
1483		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1484			return ERROR;
1485		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1486			return ERROR;
1487
1488		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1489			return ERROR;
1490		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1491			return ERROR;
1492		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1493			return ERROR;
1494
1495		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1496			return ERROR;
1497		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1498			return ERROR;
1499		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1500			return ERROR;
1501		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1502			return ERROR;
1503
1504		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1505			return ERROR;
1506		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1507			return ERROR;
1508		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1509			return ERROR;
1510
1511		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1512			return ERROR;
1513		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1514			return ERROR;
1515		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1516			return ERROR;
1517
1518		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1519			return ERROR;
1520		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1521			return ERROR;
1522		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1523			return ERROR;
1524		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1525			return ERROR;
1526
1527		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1528			return ERROR;
1529		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1530			return ERROR;
1531		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1532			return ERROR;
1533
1534		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1535			return ERROR;
1536		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1537			return ERROR;
1538		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1539			return ERROR;
1540
1541		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1542			return ERROR;
1543		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1544			return ERROR;
1545		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1546			return ERROR;
1547
1548		return NO_ERROR;
1549	}
1550
1551	template <typename T>
1552	bool Read(GLenum internalformat, const T& value, const T& expected_value)
1553	{
1554		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1555							 "  gl_Position = i_position;" NL "}";
1556		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1557		const int	  kSize   = 16;
1558		std::vector<T> data(kSize * kSize, value);
1559		GLuint		   texture;
1560		glGenTextures(1, &texture);
1561
1562		for (GLuint unit = 0; unit < 8; ++unit)
1563		{
1564			glBindTexture(GL_TEXTURE_2D, texture);
1565			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1566			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1567			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1568			glBindTexture(GL_TEXTURE_2D, 0);
1569
1570			glViewport(0, 0, kSize, kSize);
1571			glClear(GL_COLOR_BUFFER_BIT);
1572			glUseProgram(program);
1573			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1574			glBindVertexArray(m_vao);
1575			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1576
1577			if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1578			{
1579				glDeleteTextures(1, &texture);
1580				glUseProgram(0);
1581				glDeleteProgram(program);
1582				m_context.getTestContext().getLog()
1583					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1584					<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1585				return false;
1586			}
1587
1588			if (unit < 7)
1589			{
1590				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1591			}
1592		}
1593
1594		glDeleteTextures(1, &texture);
1595		glUseProgram(0);
1596		glDeleteProgram(program);
1597
1598		return true;
1599	}
1600
1601	virtual long Cleanup()
1602	{
1603		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1604		glDeleteVertexArrays(1, &m_vao);
1605		glDeleteBuffers(1, &m_vbo);
1606		return NO_ERROR;
1607	}
1608
1609	template <typename T>
1610	std::string GenFS(GLenum internalformat, const T& expected_value)
1611	{
1612		std::ostringstream os;
1613		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1614		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1615		   << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1616		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1617		   << expected_value
1618		   << ") o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
1619		return os.str();
1620	}
1621};
1622//-----------------------------------------------------------------------------
1623// 1.2.3 BasicAllFormatsStoreGeometryStages
1624//-----------------------------------------------------------------------------
1625class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1626{
1627	GLuint m_vao;
1628
1629	virtual long Setup()
1630	{
1631		glGenVertexArrays(1, &m_vao);
1632		return NO_ERROR;
1633	}
1634
1635	virtual long Run()
1636	{
1637		if (!SupportedInGeomStages(1))
1638			return NOT_SUPPORTED;
1639		glEnable(GL_RASTERIZER_DISCARD);
1640
1641		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1642			return ERROR;
1643		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1644			return ERROR;
1645		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1646			return ERROR;
1647
1648		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1649			return ERROR;
1650		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1651			return ERROR;
1652		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1653			return ERROR;
1654
1655		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1656			return ERROR;
1657		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1658			return ERROR;
1659		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1660			return ERROR;
1661
1662		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1663			return ERROR;
1664
1665		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1666			return ERROR;
1667		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1668			return ERROR;
1669		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1670			return ERROR;
1671
1672		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1673			return ERROR;
1674		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1675			return ERROR;
1676		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1677			return ERROR;
1678
1679		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1680			return ERROR;
1681		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1682			return ERROR;
1683		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1684			return ERROR;
1685		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1686			return ERROR;
1687
1688		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1689			return ERROR;
1690		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1691			return ERROR;
1692		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1693			return ERROR;
1694
1695		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1696			return ERROR;
1697		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1698			return ERROR;
1699		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1700			return ERROR;
1701
1702		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1703			return ERROR;
1704		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1705			return ERROR;
1706		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1707			return ERROR;
1708		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1709			return ERROR;
1710
1711		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1712			return ERROR;
1713		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1714			return ERROR;
1715		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1716			return ERROR;
1717
1718		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1719			return ERROR;
1720		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1721			return ERROR;
1722		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1723			return ERROR;
1724
1725		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1726			return ERROR;
1727		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1728			return ERROR;
1729		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1730			return ERROR;
1731
1732		return NO_ERROR;
1733	}
1734
1735	template <typename T>
1736	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1737	{
1738		const GLuint program =
1739			BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1740						 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1741		const int	  kSize = 1;
1742		std::vector<T> data(kSize * kSize);
1743		GLuint		   texture[4];
1744		glGenTextures(4, texture);
1745
1746		for (int i = 0; i < 4; ++i)
1747		{
1748			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1749			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1750			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1751			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1752		}
1753		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1754
1755		glUseProgram(program);
1756		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1757		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1758		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1759		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1760		for (GLuint i = 0; i < 4; ++i)
1761		{
1762			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1763		}
1764		glBindVertexArray(m_vao);
1765		glPatchParameteri(GL_PATCH_VERTICES, 1);
1766		glDrawArrays(GL_PATCHES, 0, 1);
1767		glPatchParameteri(GL_PATCH_VERTICES, 3);
1768
1769		for (int i = 0; i < 4; ++i)
1770		{
1771			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1772			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1773			glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1774
1775			if (!Equal(data[0], expected_value, internalformat))
1776			{
1777				glDeleteTextures(4, texture);
1778				glUseProgram(0);
1779				glDeleteProgram(program);
1780				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1781													<< ". Value should be: " << ToString(expected_value)
1782													<< ". Format is: " << FormatEnumToString(internalformat)
1783													<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1784				return false;
1785			}
1786		}
1787		glDeleteTextures(4, texture);
1788		glUseProgram(0);
1789		glDeleteProgram(program);
1790		return true;
1791	}
1792
1793	virtual long Cleanup()
1794	{
1795		glDisable(GL_RASTERIZER_DISCARD);
1796		glDeleteVertexArrays(1, &m_vao);
1797		return NO_ERROR;
1798	}
1799
1800	template <typename T>
1801	std::string GenVS(GLenum internalformat, const T& value)
1802	{
1803		std::ostringstream os;
1804		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1805		   << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1806								 "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  imageStore(g_image0, coord, "
1807		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1808		return os.str();
1809	}
1810
1811	template <typename T>
1812	std::string GenTCS(GLenum internalformat, const T& value)
1813	{
1814		std::ostringstream os;
1815		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1816		   << ") writeonly uniform " << TypePrefix<T>()
1817		   << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1818			  "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1819			  "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1820			  "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1821		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1822		return os.str();
1823	}
1824
1825	template <typename T>
1826	std::string GenTES(GLenum internalformat, const T& value)
1827	{
1828		std::ostringstream os;
1829		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1830		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1831		   << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1832			  "  imageStore(g_image2, coord, "
1833		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1834		return os.str();
1835	}
1836
1837	template <typename T>
1838	std::string GenGS(GLenum internalformat, const T& value)
1839	{
1840		std::ostringstream os;
1841		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1842		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1843		   << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1844			  "  imageStore(g_image3, coord, "
1845		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1846		return os.str();
1847	}
1848};
1849//-----------------------------------------------------------------------------
1850// 1.2.4 BasicAllFormatsLoadGeometryStages
1851//-----------------------------------------------------------------------------
1852class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1853{
1854	GLuint m_vao;
1855
1856	virtual long Setup()
1857	{
1858		glGenVertexArrays(1, &m_vao);
1859		return NO_ERROR;
1860	}
1861
1862	virtual long Run()
1863	{
1864		if (!SupportedInGeomStages(2))
1865			return NOT_SUPPORTED;
1866		glEnable(GL_RASTERIZER_DISCARD);
1867
1868		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1869			return ERROR;
1870		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1871			return ERROR;
1872		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1873			return ERROR;
1874
1875		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1876			return ERROR;
1877		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1878			return ERROR;
1879		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1880			return ERROR;
1881
1882		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1883			return ERROR;
1884		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1885			return ERROR;
1886		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1887			return ERROR;
1888
1889		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1890			return ERROR;
1891
1892		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1893			return ERROR;
1894		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1895			return ERROR;
1896		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1897			return ERROR;
1898
1899		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1900			return ERROR;
1901		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1902			return ERROR;
1903		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1904			return ERROR;
1905
1906		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1907			return ERROR;
1908		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1909			return ERROR;
1910		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1911			return ERROR;
1912		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1913			return ERROR;
1914
1915		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1916			return ERROR;
1917		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1918			return ERROR;
1919		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1920			return ERROR;
1921
1922		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1923			return ERROR;
1924		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1925			return ERROR;
1926		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1927			return ERROR;
1928
1929		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1930			return ERROR;
1931		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1932			return ERROR;
1933		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1934			return ERROR;
1935		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1936			return ERROR;
1937
1938		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1939			return ERROR;
1940		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1941			return ERROR;
1942		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1943			return ERROR;
1944
1945		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1946			return ERROR;
1947		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1948			return ERROR;
1949		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1950			return ERROR;
1951
1952		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1953			return ERROR;
1954		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1955			return ERROR;
1956		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1957			return ERROR;
1958
1959		return NO_ERROR;
1960	}
1961
1962	template <typename T>
1963	bool Read(GLenum internalformat, const T& value, const T& expected_value)
1964	{
1965		const GLuint program = BuildProgram(
1966			GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
1967			GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
1968		const int	  kSize = 1;
1969		std::vector<T> data(kSize * kSize, value);
1970		GLuint		   texture[8];
1971		glGenTextures(8, texture);
1972
1973		for (int i = 0; i < 4; ++i)
1974		{
1975			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1976			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1977			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1978			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1979		}
1980		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1981		vec4 zero(0);
1982		for (int i = 4; i < 8; ++i)
1983		{
1984			glBindTexture(GL_TEXTURE_2D, texture[i]);
1985			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1986			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1987			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
1988		}
1989		glBindTexture(GL_TEXTURE_2D, 0);
1990
1991		glUseProgram(program);
1992		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1993		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1994		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1995		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1996		glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
1997		glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
1998		glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
1999		glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2000
2001		for (GLuint i = 0; i < 4; ++i)
2002		{
2003			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2004		}
2005		for (GLuint i = 4; i < 8; ++i)
2006		{
2007			glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2008		}
2009		glBindVertexArray(m_vao);
2010		glPatchParameteri(GL_PATCH_VERTICES, 1);
2011		glDrawArrays(GL_PATCHES, 0, 1);
2012		glPatchParameteri(GL_PATCH_VERTICES, 3);
2013
2014		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2015		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
2016		vec4					 g_color_eps  = vec4(
2017			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2018			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2019
2020		for (int i = 0; i < 4; ++i)
2021		{
2022			glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2023			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2024			vec4 result;
2025			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2026			if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2027			{
2028				glDeleteTextures(8, texture);
2029				glUseProgram(0);
2030				glDeleteProgram(program);
2031				m_context.getTestContext().getLog()
2032					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2033					<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2034				return false;
2035			}
2036		}
2037		glDeleteTextures(8, texture);
2038		glUseProgram(0);
2039		glDeleteProgram(program);
2040		return true;
2041	}
2042
2043	virtual long Cleanup()
2044	{
2045		glDisable(GL_RASTERIZER_DISCARD);
2046		glDeleteVertexArrays(1, &m_vao);
2047		return NO_ERROR;
2048	}
2049
2050	template <typename T>
2051	std::string GenVS(GLenum internalformat, const T& expected_value)
2052	{
2053		std::ostringstream os;
2054		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2055		   << TypePrefix<T>()
2056		   << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2057			  "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2058		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2059		   << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2060								"  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2061		return os.str();
2062	}
2063
2064	template <typename T>
2065	std::string GenTCS(GLenum internalformat, const T& expected_value)
2066	{
2067		std::ostringstream os;
2068		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2069		   << ") readonly uniform " << TypePrefix<T>()
2070		   << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2071			  "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2072			  "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2073			  "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2074		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2075		   << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2076								"  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2077		return os.str();
2078	}
2079
2080	template <typename T>
2081	std::string GenTES(GLenum internalformat, const T& expected_value)
2082	{
2083		std::ostringstream os;
2084		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2085		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2086		   << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2087			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2088		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2089		   << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2090								"  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2091		return os.str();
2092	}
2093
2094	template <typename T>
2095	std::string GenGS(GLenum internalformat, const T& expected_value)
2096	{
2097		std::ostringstream os;
2098		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2099		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2100		   << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2101			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2102		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2103		   << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2104								"  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2105		return os.str();
2106	}
2107};
2108//-----------------------------------------------------------------------------
2109// 1.2.5 BasicAllFormatsLoadStoreComputeStage
2110//-----------------------------------------------------------------------------
2111class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2112{
2113	virtual long Run()
2114	{
2115		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2116		{
2117			m_context.getTestContext().getLog()
2118				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2119				<< tcu::TestLog::EndMessage;
2120			return NOT_SUPPORTED;
2121		}
2122
2123		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2124			return ERROR;
2125		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2126			return ERROR;
2127		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2128			return ERROR;
2129
2130		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2131			return ERROR;
2132		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2133			return ERROR;
2134		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2135			return ERROR;
2136
2137		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2138			return ERROR;
2139		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2140			return ERROR;
2141		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2142			return ERROR;
2143
2144		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2145			return ERROR;
2146
2147		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2148			return ERROR;
2149		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2150			return ERROR;
2151		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2152			return ERROR;
2153
2154		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2155			return ERROR;
2156		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2157			return ERROR;
2158		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2159			return ERROR;
2160
2161		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2162			return ERROR;
2163		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2164			return ERROR;
2165		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2166			return ERROR;
2167		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2168			return ERROR;
2169
2170		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2171			return ERROR;
2172		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2173			return ERROR;
2174		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2175			return ERROR;
2176
2177		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2178			return ERROR;
2179		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2180			return ERROR;
2181		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2182			return ERROR;
2183
2184		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2185			return ERROR;
2186		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2187			return ERROR;
2188		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2189			return ERROR;
2190		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2191			return ERROR;
2192
2193		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2194			return ERROR;
2195		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2196			return ERROR;
2197		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2198			return ERROR;
2199
2200		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2201			return ERROR;
2202		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2203			return ERROR;
2204		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2205			return ERROR;
2206
2207		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2208			return ERROR;
2209		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2210			return ERROR;
2211		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2212			return ERROR;
2213
2214		return NO_ERROR;
2215	}
2216
2217	template <typename T>
2218	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2219	{
2220		GLuint			  program;
2221		std::string		  source = GenCS<T>(internalformat);
2222		const char* const src	= source.c_str();
2223		GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
2224		glShaderSource(sh, 1, &src, NULL);
2225		glCompileShader(sh);
2226		program = glCreateProgram();
2227		glAttachShader(program, sh);
2228		glLinkProgram(program);
2229		glDeleteShader(sh);
2230
2231		const int	  kSize = 1;
2232		std::vector<T> data(kSize * kSize, value);
2233		GLuint		   texture[2];
2234		glGenTextures(2, texture);
2235
2236		glBindTexture(GL_TEXTURE_2D, texture[0]);
2237		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2238		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2239		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2240		glBindTexture(GL_TEXTURE_2D, texture[1]);
2241		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2242		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2243		vec4 zero(0);
2244		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2245
2246		glBindTexture(GL_TEXTURE_2D, 0);
2247
2248		glUseProgram(program);
2249		glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2250		glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2251
2252		glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2253		glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2254
2255		glDispatchCompute(1, 1, 1);
2256
2257		for (int i = 0; i < 2; ++i)
2258		{
2259			glBindTexture(GL_TEXTURE_2D, texture[i]);
2260			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2261			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2262
2263			if (!Equal(data[0], expected_value, internalformat))
2264			{
2265				glDeleteTextures(4, texture);
2266				glUseProgram(0);
2267				glDeleteProgram(program);
2268				m_context.getTestContext().getLog()
2269					<< tcu::TestLog::Message << "Value is: " << ToString(data[0])
2270					<< ". Value should be: " << ToString(expected_value)
2271					<< ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2272				return false;
2273			}
2274		}
2275		glDeleteTextures(2, texture);
2276		glUseProgram(0);
2277		glDeleteProgram(program);
2278		return true;
2279	}
2280
2281	template <typename T>
2282	std::string GenCS(GLenum internalformat)
2283	{
2284		std::ostringstream os;
2285		os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2286			  "layout("
2287		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2288		   << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2289		   << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2290								 "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2291		   << TypePrefix<T>()
2292		   << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2293		return os.str();
2294	}
2295};
2296//-----------------------------------------------------------------------------
2297// 1.3.1 BasicAllTargetsStore
2298//-----------------------------------------------------------------------------
2299class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2300{
2301	GLuint m_vao;
2302	GLuint m_vbo;
2303
2304	virtual long Setup()
2305	{
2306		m_vao = 0;
2307		m_vbo = 0;
2308		return NO_ERROR;
2309	}
2310
2311	virtual long Run()
2312	{
2313		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2314
2315		if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2316			return ERROR;
2317		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2318			return ERROR;
2319		if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2320			return ERROR;
2321
2322		if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2323			return ERROR;
2324		if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2325			return ERROR;
2326		if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2327			return ERROR;
2328
2329		if (SupportedSamples(4))
2330		{
2331			if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2332				return ERROR;
2333
2334			GLint isamples;
2335			glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2336			if (isamples >= 4)
2337			{
2338				if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2339					return ERROR;
2340				if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2341					return ERROR;
2342			}
2343		}
2344		return NO_ERROR;
2345	}
2346
2347	virtual long Cleanup()
2348	{
2349		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2350		glDeleteVertexArrays(1, &m_vao);
2351		glDeleteBuffers(1, &m_vbo);
2352		return NO_ERROR;
2353	}
2354
2355	template <typename T>
2356	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2357	{
2358		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2359							 "  gl_Position = i_position;" NL "}";
2360		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2361		GLuint		 textures[8];
2362		GLuint		 buffer;
2363		glGenTextures(8, textures);
2364		glGenBuffers(1, &buffer);
2365
2366		const int	  kSize = 16;
2367		std::vector<T> data(kSize * kSize * 2);
2368
2369		glBindTexture(GL_TEXTURE_1D, textures[0]);
2370		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2371		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2372		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2373		glBindTexture(GL_TEXTURE_1D, 0);
2374
2375		glBindTexture(GL_TEXTURE_2D, textures[1]);
2376		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2377		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2378		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2379		glBindTexture(GL_TEXTURE_2D, 0);
2380
2381		glBindTexture(GL_TEXTURE_3D, textures[2]);
2382		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2383		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2384		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2385		glBindTexture(GL_TEXTURE_3D, 0);
2386
2387		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2388		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2389		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2390		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2391		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2392
2393		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2394		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2395		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2396		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2397					 &data[0]);
2398		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2399					 &data[0]);
2400		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2401					 &data[0]);
2402		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2403					 &data[0]);
2404		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2405					 &data[0]);
2406		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2407					 &data[0]);
2408		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2409
2410		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2411		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2412		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2413		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2414		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2415		glBindTexture(GL_TEXTURE_BUFFER, 0);
2416
2417		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2418		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2419		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2420		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2421		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2422
2423		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2424		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2425		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2426		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2427		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2428
2429		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2430		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2431		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2432		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2433		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2434		glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2435		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2436		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2437
2438		glUseProgram(program);
2439		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2440		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2441		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2442		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2443		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2444		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2445		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2446		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2447
2448		glBindVertexArray(m_vao);
2449		glViewport(0, 0, kSize, kSize);
2450		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2451
2452		bool status = true;
2453
2454		glBindTexture(GL_TEXTURE_1D, textures[0]);
2455		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2456		glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2457		glBindTexture(GL_TEXTURE_1D, 0);
2458		for (int i = 0; i < kSize; ++i)
2459		{
2460			if (!tcu::allEqual(data[i], expected_value))
2461			{
2462				status = false;
2463				m_context.getTestContext().getLog()
2464					<< tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2465					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2466				break;
2467			}
2468		}
2469		std::fill(data.begin(), data.end(), T(0));
2470
2471		glBindTexture(GL_TEXTURE_2D, textures[1]);
2472		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2473		glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2474		glBindTexture(GL_TEXTURE_2D, 0);
2475		for (int i = 0; i < kSize * kSize; ++i)
2476		{
2477			if (!tcu::allEqual(data[i], expected_value))
2478			{
2479				status = false;
2480				m_context.getTestContext().getLog()
2481					<< tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2482					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2483				break;
2484			}
2485		}
2486
2487		glBindTexture(GL_TEXTURE_3D, textures[2]);
2488		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2489		glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2490		glBindTexture(GL_TEXTURE_3D, 0);
2491		for (int i = 0; i < kSize * kSize * 2; ++i)
2492		{
2493			if (!tcu::allEqual(data[i], expected_value))
2494			{
2495				status = false;
2496				m_context.getTestContext().getLog()
2497					<< tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2498					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2499				break;
2500			}
2501		}
2502
2503		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2504		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2505		glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2506		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2507		for (int i = 0; i < kSize * kSize; ++i)
2508		{
2509			if (!tcu::allEqual(data[i], expected_value))
2510			{
2511				status = false;
2512				m_context.getTestContext().getLog()
2513					<< tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2514					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2515				break;
2516			}
2517		}
2518
2519		{
2520			glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2521			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2522			for (int face = 0; face < 6; ++face)
2523			{
2524				glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2525				for (int i = 0; i < kSize * kSize; ++i)
2526				{
2527					if (!tcu::allEqual(data[i], expected_value))
2528					{
2529						status = false;
2530						m_context.getTestContext().getLog()
2531							<< tcu::TestLog::Message
2532							<< "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2533							<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2534						break;
2535					}
2536				}
2537			}
2538			glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2539		}
2540
2541		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2542		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2543		glBindTexture(GL_TEXTURE_BUFFER, 0);
2544		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2545		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2546		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2547		for (int i = 0; i < kSize; ++i)
2548		{
2549			if (!tcu::allEqual(data[i], expected_value))
2550			{
2551				status = false;
2552				m_context.getTestContext().getLog()
2553					<< tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2554					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2555				break;
2556			}
2557		}
2558
2559		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2560		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2561		glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2562		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2563		for (int i = 0; i < kSize * 2; ++i)
2564		{
2565			if (!tcu::allEqual(data[i], expected_value))
2566			{
2567				status = false;
2568				m_context.getTestContext().getLog()
2569					<< tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2570					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2571				break;
2572			}
2573		}
2574
2575		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2576		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2577		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2578		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2579		for (int i = 0; i < kSize * kSize * 2; ++i)
2580		{
2581			if (!tcu::allEqual(data[i], expected_value))
2582			{
2583				status = false;
2584				m_context.getTestContext().getLog()
2585					<< tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2586					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2587				break;
2588			}
2589		}
2590
2591		glUseProgram(0);
2592		glDeleteProgram(program);
2593		glDeleteTextures(8, textures);
2594		glDeleteBuffers(1, &buffer);
2595
2596		return status;
2597	}
2598
2599	template <typename T>
2600	bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2601	{
2602
2603		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2604							 "  gl_Position = i_position;" NL "}";
2605		const GLuint program	 = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2606		const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2607		GLuint		 textures[2];
2608		glGenTextures(2, textures);
2609
2610		const int kSize = 16;
2611
2612		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2613		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2614		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2615
2616		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2617		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2618		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2619
2620		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2621		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2622
2623		glClear(GL_COLOR_BUFFER_BIT);
2624		glUseProgram(program);
2625		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2626		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2627
2628		glBindVertexArray(m_vao);
2629		glViewport(0, 0, kSize, kSize);
2630		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2631
2632		bool status = true;
2633
2634		glActiveTexture(GL_TEXTURE0);
2635		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2636		glActiveTexture(GL_TEXTURE1);
2637		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2638
2639		glUseProgram(val_program);
2640		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2641		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2642
2643		glBindVertexArray(m_vao);
2644		glViewport(0, 0, kSize, kSize);
2645		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2646		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2647
2648		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2649		{
2650			status = false;
2651			m_context.getTestContext().getLog()
2652				<< tcu::TestLog::Message
2653				<< "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2654				<< tcu::TestLog::EndMessage;
2655		}
2656
2657		glActiveTexture(GL_TEXTURE0);
2658		glDeleteTextures(2, textures);
2659		glUseProgram(0);
2660		glDeleteProgram(program);
2661		glDeleteProgram(val_program);
2662
2663		return status;
2664	}
2665
2666	template <typename T>
2667	bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2668	{
2669		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2670							 "  gl_Position = i_position;" NL "}";
2671		const GLuint program =
2672			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2673		GLuint textures[1];
2674		glGenTextures(1, textures);
2675
2676		const int kSize = 16;
2677
2678		std::vector<T> data(kSize * kSize * 12);
2679		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2680		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2681		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2682					 &data[0]);
2683		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2684
2685		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2686
2687		glUseProgram(program);
2688		glBindVertexArray(m_vao);
2689		glViewport(0, 0, kSize, kSize);
2690		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2691
2692		bool status = true;
2693
2694		std::fill(data.begin(), data.end(), T(0));
2695		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2696		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2697		glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2698		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2699		for (int i = 0; i < kSize * kSize * 12; ++i)
2700		{
2701			if (!tcu::allEqual(data[i], expected_value))
2702			{
2703				status = false;
2704				m_context.getTestContext().getLog()
2705					<< tcu::TestLog::Message
2706					<< "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2707					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2708				break;
2709			}
2710		}
2711
2712		glDeleteTextures(1, textures);
2713		glUseProgram(0);
2714		glDeleteProgram(program);
2715
2716		return status;
2717	}
2718
2719	template <typename T>
2720	std::string GenFS(GLenum internalformat, const T& write_value)
2721	{
2722		std::ostringstream os;
2723		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2724		   << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2725		   << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2726		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2727		   << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2728		   << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2729		   << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2730		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2731		   << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2732		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2733		   << ") writeonly uniform " << TypePrefix<T>()
2734		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2735			  "  imageStore(g_image_1d, coord.x, "
2736		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2737		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2738		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2739		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2740		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2741		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2742		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2743		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2744		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2745		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2746		   << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2747		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2748		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2749		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2750		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2751		   << write_value << ");" NL "  discard;" NL "}";
2752		return os.str();
2753	}
2754
2755	template <typename T>
2756	std::string GenFSMS(GLenum internalformat, const T& write_value)
2757	{
2758		std::ostringstream os;
2759		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2760		   << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2761		   << ") writeonly uniform " << TypePrefix<T>()
2762		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2763			  "  imageStore(g_image_2dms, coord, 0, "
2764		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2765		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2766		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2767		   << TypePrefix<T>() << "vec4" << write_value
2768		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2769		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2770		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2771		   << TypePrefix<T>() << "vec4" << write_value
2772		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2773		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2774		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2775		   << TypePrefix<T>() << "vec4" << write_value
2776		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2777		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2778		   << "vec4" << write_value << ");" NL "  discard;" NL "}";
2779		return os.str();
2780	}
2781
2782	template <typename T>
2783	std::string GenFSMSVal(const T& expected_value)
2784	{
2785		std::ostringstream os;
2786		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2787		   << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2788		   << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2789			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2790		   << TypePrefix<T>() << "vec4" << expected_value
2791		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2792		   << TypePrefix<T>() << "vec4" << expected_value
2793		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2794		   << TypePrefix<T>() << "vec4" << expected_value
2795		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2796		   << TypePrefix<T>() << "vec4" << expected_value
2797		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2798			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2799		   << TypePrefix<T>() << "vec4" << expected_value
2800		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2801			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2802		   << TypePrefix<T>() << "vec4" << expected_value
2803		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2804			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2805		   << TypePrefix<T>() << "vec4" << expected_value
2806		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2807			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2808		   << TypePrefix<T>() << "vec4" << expected_value
2809		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2810			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2811		   << TypePrefix<T>() << "vec4" << expected_value
2812		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2813			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2814		   << TypePrefix<T>() << "vec4" << expected_value
2815		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2816			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2817		   << TypePrefix<T>() << "vec4" << expected_value
2818		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2819			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2820		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2821		return os.str();
2822	}
2823
2824	template <typename T>
2825	std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2826	{
2827		std::ostringstream os;
2828		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2829		   << TypePrefix<T>()
2830		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2831			  "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2832		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2833		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2834		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2835		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2836		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2837		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2838		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2839		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2840		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2841		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2842		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2843		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2844		return os.str();
2845	}
2846};
2847//-----------------------------------------------------------------------------
2848// 1.3.2.1 BasicAllTargetsLoadNonMS
2849//-----------------------------------------------------------------------------
2850class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2851{
2852	GLuint m_vao;
2853	GLuint m_vbo;
2854
2855	virtual long Setup()
2856	{
2857		m_vao = 0;
2858		m_vbo = 0;
2859		return NO_ERROR;
2860	}
2861
2862	virtual long Run()
2863	{
2864		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2865
2866		if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2867			return ERROR;
2868		if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2869			return ERROR;
2870		if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2871			return ERROR;
2872
2873		if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2874			return ERROR;
2875		if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2876			return ERROR;
2877		if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2878			return ERROR;
2879
2880		return NO_ERROR;
2881	}
2882
2883	virtual long Cleanup()
2884	{
2885		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2886		glDeleteVertexArrays(1, &m_vao);
2887		glDeleteBuffers(1, &m_vbo);
2888		return NO_ERROR;
2889	}
2890
2891	template <typename T>
2892	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2893	{
2894		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2895							 "  gl_Position = i_position;" NL "}";
2896		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2897		GLuint		 textures[7];
2898		GLuint		 buffer;
2899		glGenTextures(7, textures);
2900		glGenBuffers(1, &buffer);
2901
2902		const int	  kSize = 16;
2903		std::vector<T> data(kSize * kSize * 2, value);
2904
2905		glBindTexture(GL_TEXTURE_1D, textures[0]);
2906		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2907		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2908		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2909		glBindTexture(GL_TEXTURE_1D, 0);
2910
2911		glBindTexture(GL_TEXTURE_2D, textures[1]);
2912		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2913		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2914		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2915		glBindTexture(GL_TEXTURE_2D, 0);
2916
2917		glBindTexture(GL_TEXTURE_3D, textures[2]);
2918		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2919		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2920		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2921		glBindTexture(GL_TEXTURE_3D, 0);
2922
2923		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2924		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2925		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2926		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2927		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2928
2929		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2930		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2931		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2932		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2933		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2934		glBindTexture(GL_TEXTURE_BUFFER, 0);
2935
2936		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2937		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2938		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2939		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2940		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2941
2942		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2943		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2944		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2945		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2946		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2947
2948		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2949		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2950		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2951		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2952		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2953		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2954		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2955
2956		glClear(GL_COLOR_BUFFER_BIT);
2957
2958		glUseProgram(program);
2959		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2960		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2961		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2962		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2963		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
2964		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
2965		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
2966
2967		glBindVertexArray(m_vao);
2968		glViewport(0, 0, kSize, kSize);
2969		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2970
2971		bool status = true;
2972
2973		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2974		{
2975			status = false;
2976		}
2977
2978		std::map<std::string, GLuint> name_index_map;
2979		GLint uniforms;
2980		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
2981		if (uniforms != 7)
2982		{
2983			status = false;
2984			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
2985												<< " should be 7." << tcu::TestLog::EndMessage;
2986		}
2987		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
2988		{
2989			GLchar name[32];
2990			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
2991			name_index_map.insert(std::make_pair(std::string(name), index));
2992		}
2993
2994		if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
2995			status = false;
2996		if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
2997			status = false;
2998		if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
2999			status = false;
3000		if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3001			status = false;
3002		if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3003			status = false;
3004		if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3005			status = false;
3006		if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3007			status = false;
3008
3009		glUseProgram(0);
3010		glDeleteProgram(program);
3011		glDeleteTextures(7, textures);
3012		glDeleteBuffers(1, &buffer);
3013
3014		return status;
3015	}
3016
3017	template <typename T>
3018	bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3019	{
3020		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3021							 "  gl_Position = i_position;" NL "}";
3022		const GLuint program =
3023			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3024		GLuint textures[2];
3025		glGenTextures(2, textures);
3026
3027		const int	  kSize = 16;
3028		std::vector<T> data(kSize * kSize * 12, value);
3029
3030		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3031		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3032		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3033		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3034					 &data[0]);
3035		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3036					 &data[0]);
3037		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3038					 &data[0]);
3039		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3040					 &data[0]);
3041		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3042					 &data[0]);
3043		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3044					 &data[0]);
3045		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3046
3047		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3048		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3049		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3050		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3051					 &data[0]);
3052		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3053
3054		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3055		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3056
3057		glClear(GL_COLOR_BUFFER_BIT);
3058
3059		glUseProgram(program);
3060		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3061		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3062
3063		glBindVertexArray(m_vao);
3064		glViewport(0, 0, kSize, kSize);
3065		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3066
3067		bool status = true;
3068
3069		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3070		{
3071			status = false;
3072		}
3073
3074		std::map<std::string, GLuint> name_index_map;
3075		GLint uniforms;
3076		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3077		if (uniforms != 2)
3078		{
3079			status = false;
3080			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3081												<< " should be 2." << tcu::TestLog::EndMessage;
3082		}
3083		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3084		{
3085			GLchar name[32];
3086			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3087			name_index_map.insert(std::make_pair(std::string(name), index));
3088		}
3089
3090		if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3091			status = false;
3092		if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3093			status = false;
3094
3095		glUseProgram(0);
3096		glDeleteProgram(program);
3097		glDeleteTextures(2, textures);
3098
3099		return status;
3100	}
3101
3102	template <typename T>
3103	std::string GenFS(GLenum internalformat, const T& expected_value)
3104	{
3105		std::ostringstream os;
3106		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3107		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3108		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3109		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3110		   << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3111		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3112		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3113		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3114		   << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3115		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3116		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3117			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3118		   << TypePrefix<T>()
3119		   << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3120		   << expected_value
3121		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3122		   << TypePrefix<T>() << "vec4" << expected_value
3123		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3124			  "  if (v != "
3125		   << TypePrefix<T>() << "vec4" << expected_value
3126		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3127			  "  if (v != "
3128		   << TypePrefix<T>() << "vec4" << expected_value
3129		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3130		   << TypePrefix<T>() << "vec4" << expected_value
3131		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3132		   << TypePrefix<T>() << "vec4" << expected_value
3133		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3134			  "  if (v != "
3135		   << TypePrefix<T>() << "vec4" << expected_value
3136		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3137			  "  if (v != "
3138		   << TypePrefix<T>() << "vec4" << expected_value
3139		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3140			  "  if (v != "
3141		   << TypePrefix<T>() << "vec4" << expected_value
3142		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3143			  "  if (v != "
3144		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3145		return os.str();
3146	}
3147
3148	template <typename T>
3149	std::string GenFSCube(GLenum internalformat, const T& expected_value)
3150	{
3151		std::ostringstream os;
3152		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3153		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3154		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3155		   << TypePrefix<T>()
3156		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3157			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3158		   << TypePrefix<T>()
3159		   << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3160		   << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3161										  "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  if (v != "
3162		   << TypePrefix<T>() << "vec4" << expected_value
3163		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3164			  "  if (v != "
3165		   << TypePrefix<T>() << "vec4" << expected_value
3166		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3167			  "  if (v != "
3168		   << TypePrefix<T>() << "vec4" << expected_value
3169		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3170			  "  if (v != "
3171		   << TypePrefix<T>() << "vec4" << expected_value
3172		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3173			  "  if (v != "
3174		   << TypePrefix<T>() << "vec4" << expected_value
3175		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3176			  "  if (v != "
3177		   << TypePrefix<T>() << "vec4" << expected_value
3178		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3179			  "  if (v != "
3180		   << TypePrefix<T>() << "vec4" << expected_value
3181		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3182			  "  if (v != "
3183		   << TypePrefix<T>() << "vec4" << expected_value
3184		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3185			  "  if (v != "
3186		   << TypePrefix<T>() << "vec4" << expected_value
3187		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3188			  "  if (v != "
3189		   << TypePrefix<T>() << "vec4" << expected_value
3190		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3191			  "  if (v != "
3192		   << TypePrefix<T>() << "vec4" << expected_value
3193		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3194			  "  if (v != "
3195		   << TypePrefix<T>() << "vec4" << expected_value
3196		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3197			  "  if (v != "
3198		   << TypePrefix<T>() << "vec4" << expected_value
3199		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3200			  "  if (v != "
3201		   << TypePrefix<T>() << "vec4" << expected_value
3202		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3203			  "  if (v != "
3204		   << TypePrefix<T>() << "vec4" << expected_value
3205		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3206			  "  if (v != "
3207		   << TypePrefix<T>() << "vec4" << expected_value
3208		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3209			  "  if (v != "
3210		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3211		return os.str();
3212	}
3213};
3214//-----------------------------------------------------------------------------
3215// 1.3.2.2 BasicAllTargetsLoadMS
3216//-----------------------------------------------------------------------------
3217class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3218{
3219	GLuint m_vao;
3220	GLuint m_vbo;
3221
3222	virtual long Setup()
3223	{
3224		m_vao = 0;
3225		m_vbo = 0;
3226		return NO_ERROR;
3227	}
3228
3229	virtual long Run()
3230	{
3231		if (!SupportedSamples(4))
3232			return NOT_SUPPORTED;
3233
3234		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3235
3236		if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3237			return ERROR;
3238
3239		GLint isamples;
3240		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3241		if (isamples >= 4)
3242		{
3243			if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3244				return ERROR;
3245			if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3246				return ERROR;
3247		}
3248
3249		return NO_ERROR;
3250	}
3251
3252	virtual long Cleanup()
3253	{
3254		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3255		glDeleteVertexArrays(1, &m_vao);
3256		glDeleteBuffers(1, &m_vbo);
3257		return NO_ERROR;
3258	}
3259
3260	template <typename T>
3261	bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3262	{
3263		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3264							 "  gl_Position = i_position;" NL "}";
3265		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3266		GLuint		 textures[2];
3267		glGenTextures(2, textures);
3268
3269		const int kSize = 16;
3270
3271		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3272		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3273		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3274
3275		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3276		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3277		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3278
3279		GLuint fbo;
3280		glGenFramebuffers(1, &fbo);
3281		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3282		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3283		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3284		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3285		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3286		glDrawBuffers(3, draw_buffers);
3287		ClearBuffer(GL_COLOR, 0, value);
3288		ClearBuffer(GL_COLOR, 1, value);
3289		ClearBuffer(GL_COLOR, 2, value);
3290		glDeleteFramebuffers(1, &fbo);
3291
3292		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3293		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3294
3295		glUseProgram(program);
3296		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3297		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3298
3299		glClear(GL_COLOR_BUFFER_BIT);
3300		glBindVertexArray(m_vao);
3301		glViewport(0, 0, kSize, kSize);
3302		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3303
3304		bool status = true;
3305
3306		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3307		{
3308			status = false;
3309		}
3310
3311		std::map<std::string, GLuint> name_index_map;
3312		GLint uniforms;
3313		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3314		if (uniforms != 2)
3315		{
3316			status = false;
3317			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3318												<< " should be 2." << tcu::TestLog::EndMessage;
3319		}
3320		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3321		{
3322			GLchar name[32];
3323			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3324			name_index_map.insert(std::make_pair(std::string(name), index));
3325		}
3326
3327		if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3328			status = false;
3329		if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3330						  ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3331			status = false;
3332
3333		glDeleteTextures(2, textures);
3334		glUseProgram(0);
3335		glDeleteProgram(program);
3336
3337		return status;
3338	}
3339
3340	template <typename T>
3341	std::string GenFSMS(GLenum internalformat, const T& expected_value)
3342	{
3343		std::ostringstream os;
3344		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3345		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3346		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3347		   << TypePrefix<T>()
3348		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3349			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3350		   << TypePrefix<T>() << "vec4" << expected_value
3351		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3352		   << TypePrefix<T>() << "vec4" << expected_value
3353		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3354		   << TypePrefix<T>() << "vec4" << expected_value
3355		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3356		   << TypePrefix<T>() << "vec4" << expected_value
3357		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3358		   << TypePrefix<T>() << "vec4" << expected_value
3359		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3360		   << TypePrefix<T>() << "vec4" << expected_value
3361		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3362		   << TypePrefix<T>() << "vec4" << expected_value
3363		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3364		   << TypePrefix<T>() << "vec4" << expected_value
3365		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3366		   << TypePrefix<T>() << "vec4" << expected_value
3367		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3368		   << TypePrefix<T>() << "vec4" << expected_value
3369		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3370		   << TypePrefix<T>() << "vec4" << expected_value
3371		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3372		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3373		return os.str();
3374	}
3375};
3376//-----------------------------------------------------------------------------
3377// 1.3.3 BasicAllTargetsAtomic
3378//-----------------------------------------------------------------------------
3379class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3380{
3381	GLuint m_vao;
3382	GLuint m_vbo;
3383
3384	virtual long Setup()
3385	{
3386		m_vao = 0;
3387		m_vbo = 0;
3388		return NO_ERROR;
3389	}
3390
3391	virtual long Run()
3392	{
3393		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3394
3395		if (!Atomic<GLint>(GL_R32I))
3396			return ERROR;
3397		if (!Atomic<GLuint>(GL_R32UI))
3398			return ERROR;
3399
3400		if (!AtomicCube<GLint>(GL_R32I))
3401			return ERROR;
3402		if (!AtomicCube<GLuint>(GL_R32UI))
3403			return ERROR;
3404
3405		GLint isamples;
3406		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3407		if (SupportedSamples(4) && isamples >= 4)
3408		{
3409			if (!AtomicMS<GLint>(GL_R32I))
3410				return ERROR;
3411			if (!AtomicMS<GLuint>(GL_R32UI))
3412				return ERROR;
3413		}
3414
3415		return NO_ERROR;
3416	}
3417
3418	virtual long Cleanup()
3419	{
3420		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3421		glDeleteVertexArrays(1, &m_vao);
3422		glDeleteBuffers(1, &m_vbo);
3423		return NO_ERROR;
3424	}
3425
3426	template <typename T>
3427	bool Atomic(GLenum internalformat)
3428	{
3429		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3430							 "  gl_Position = i_position;" NL "}";
3431		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3432		GLuint		 textures[7];
3433		GLuint		 buffer;
3434		glGenTextures(7, textures);
3435		glGenBuffers(1, &buffer);
3436
3437		const int	  kSize = 16;
3438		std::vector<T> data(kSize * kSize * 2);
3439
3440		glBindTexture(GL_TEXTURE_1D, textures[0]);
3441		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3442		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3443		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3444		glBindTexture(GL_TEXTURE_1D, 0);
3445
3446		glBindTexture(GL_TEXTURE_2D, textures[1]);
3447		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3448		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3449		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3450		glBindTexture(GL_TEXTURE_2D, 0);
3451
3452		glBindTexture(GL_TEXTURE_3D, textures[2]);
3453		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3454		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3455		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3456		glBindTexture(GL_TEXTURE_3D, 0);
3457
3458		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3459		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3460		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3461		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3462		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3463
3464		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3465		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3466		glBindBuffer(GL_TEXTURE_BUFFER, 0);
3467		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3468		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3469		glBindTexture(GL_TEXTURE_BUFFER, 0);
3470
3471		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3472		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3473		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3474		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3475		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3476
3477		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3478		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3479		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3480		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3481		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3482
3483		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3484		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3485		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3486		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3487		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3488		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3489		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3490
3491		glClear(GL_COLOR_BUFFER_BIT);
3492
3493		glUseProgram(program);
3494		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3495		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3496		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3497		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3498		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3499		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3500		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3501
3502		glBindVertexArray(m_vao);
3503		glViewport(0, 0, kSize, 1);
3504		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3505
3506		bool status = true;
3507
3508		if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3509		{
3510			status = false;
3511		}
3512
3513		glUseProgram(0);
3514		glDeleteProgram(program);
3515		glDeleteTextures(7, textures);
3516		glDeleteBuffers(1, &buffer);
3517
3518		return status;
3519	}
3520
3521	template <typename T>
3522	bool AtomicCube(GLenum internalformat)
3523	{
3524		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3525							 "  gl_Position = i_position;" NL "}";
3526		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3527		GLuint		 textures[2];
3528		glGenTextures(2, textures);
3529
3530		const int	  kSize = 16;
3531		std::vector<T> data(kSize * kSize * 12);
3532
3533		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3534		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3535		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3536		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3537					 &data[0]);
3538		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3539					 &data[0]);
3540		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3541					 &data[0]);
3542		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3543					 &data[0]);
3544		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3545					 &data[0]);
3546		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3547					 &data[0]);
3548		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3549
3550		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3551		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3552		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3553		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3554					 &data[0]);
3555		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3556
3557		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3558		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3559
3560		glClear(GL_COLOR_BUFFER_BIT);
3561
3562		glUseProgram(program);
3563		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3564		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3565
3566		glBindVertexArray(m_vao);
3567		glViewport(0, 0, kSize, kSize);
3568		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3569
3570		bool status = true;
3571
3572		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3573		{
3574			status = false;
3575		}
3576
3577		glUseProgram(0);
3578		glDeleteProgram(program);
3579		glDeleteTextures(2, textures);
3580
3581		return status;
3582	}
3583
3584	template <typename T>
3585	bool AtomicMS(GLenum internalformat)
3586	{
3587		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3588							 "  gl_Position = i_position;" NL "}";
3589		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3590		GLuint		 textures[2];
3591		glGenTextures(2, textures);
3592
3593		const int kSize = 16;
3594
3595		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3596		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3597		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3598
3599		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3600		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3601		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3602
3603		GLuint fbo;
3604		glGenFramebuffers(1, &fbo);
3605		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3606		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3607		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3608		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3609		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3610		glDrawBuffers(3, draw_buffers);
3611		if (internalformat == GL_R32I)
3612		{
3613			const GLint value[4] = { 0, 0, 0, 0 };
3614			glClearBufferiv(GL_COLOR, 0, value);
3615			glClearBufferiv(GL_COLOR, 1, value);
3616			glClearBufferiv(GL_COLOR, 2, value);
3617		}
3618		else
3619		{
3620			const GLuint value[4] = { 0, 0, 0, 0 };
3621			glClearBufferuiv(GL_COLOR, 0, value);
3622			glClearBufferuiv(GL_COLOR, 1, value);
3623			glClearBufferuiv(GL_COLOR, 2, value);
3624		}
3625		glDeleteFramebuffers(1, &fbo);
3626
3627		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3628		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3629
3630		glUseProgram(program);
3631		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3632		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3633
3634		glClear(GL_COLOR_BUFFER_BIT);
3635		glBindVertexArray(m_vao);
3636		glViewport(0, 0, kSize, kSize);
3637		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3638
3639		bool status = true;
3640
3641		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3642		{
3643			status = false;
3644		}
3645
3646		glDeleteTextures(2, textures);
3647		glUseProgram(0);
3648		glDeleteProgram(program);
3649
3650		return status;
3651	}
3652
3653	template <typename T>
3654	std::string GenFS(GLenum internalformat)
3655	{
3656		std::ostringstream os;
3657		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3658		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3659		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3660		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3661		   << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3662		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3663		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3664		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3665		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3666		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3667		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3668			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3669
3670			NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3671			  "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3672			  "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3673			  "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3674			  "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3675			  "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3676			  "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3677			  "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3678			  "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3679
3680			NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3681			  "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3682			  "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3683			  "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3684			  "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3685			  "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3686			  "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3687			  "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3688			  "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3689
3690			NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3691			  "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3692			  "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3693			  "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3694			  "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3695			  "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3696			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3697			  "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3698			  "1.0);" NL
3699			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3700
3701			NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3702			  "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3703			  "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3704			  "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3705			  "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3706			  "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3707			  "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3708			  "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3709			  "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3710
3711			NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3712			  "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3713			  "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3714			  "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3715			  "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716			  "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718			  "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3720
3721			NL
3722			  "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3723			  "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3724			  "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3725			  "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726			  "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727			  "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728			  "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3729			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3730			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3731			  "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3732
3733			NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3734			  "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3735			  "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736			  "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737			  "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738			  "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739			  "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3740			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3741			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3742			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3743		return os.str();
3744	}
3745
3746	template <typename T>
3747	std::string GenFSCube(GLenum internalformat)
3748	{
3749		std::ostringstream os;
3750		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3751		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3752		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3753		   << TypePrefix<T>()
3754		   << "imageCube g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3755			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3756
3757			NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758			  "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759			  "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760			  "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761			  "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762			  "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3764			  "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3765			  "1.0);" NL
3766			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3767
3768			NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3769			  "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3770			  "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3771			  "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3772			  "ivec3(coord, 0), 0) != 4) o_color = "
3773			  "vec4(1.0, 0.0, 0.0, 1.0);" NL
3774			  "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3775			  "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3776			  "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3777			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3778			  "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779			  "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3780			  "1.0);" NL "}";
3781		return os.str();
3782	}
3783
3784	template <typename T>
3785	std::string GenFSMS(GLenum internalformat)
3786	{
3787		std::ostringstream os;
3788		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3789		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3790		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3791		   << TypePrefix<T>()
3792		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3793			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3794			  "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3795			  "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3796			  "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3797			  "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3798			  "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3799			  "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3800			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3801			  "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3802			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3803			  "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3804			  "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3805			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3806			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807			  "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3808			  "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3809			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3810			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3811			  "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3812			  "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3813			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3814			  "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3815			  "0.0, 1.0);" NL "}";
3816		return os.str();
3817	}
3818};
3819//-----------------------------------------------------------------------------
3820// LoadStoreMachine
3821//-----------------------------------------------------------------------------
3822class LoadStoreMachine : public ShaderImageLoadStoreBase
3823{
3824	GLuint m_vao;
3825	int	m_stage;
3826
3827	virtual long Setup()
3828	{
3829		glGenVertexArrays(1, &m_vao);
3830		return NO_ERROR;
3831	}
3832
3833	virtual long Cleanup()
3834	{
3835		glDisable(GL_RASTERIZER_DISCARD);
3836		glDeleteVertexArrays(1, &m_vao);
3837		return NO_ERROR;
3838	}
3839
3840	template <typename T>
3841	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3842	{
3843		const GLenum targets[] = { GL_TEXTURE_1D,		GL_TEXTURE_2D,
3844								   GL_TEXTURE_3D,		GL_TEXTURE_RECTANGLE,
3845								   GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3846								   GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3847		const int kTargets		= sizeof(targets) / sizeof(targets[0]);
3848		GLuint	program_store = 0;
3849		GLuint	program_load  = 0;
3850		if (m_stage == 0)
3851		{ // VS
3852			program_store =
3853				BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3854			program_load =
3855				BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3856		}
3857		else if (m_stage == 1)
3858		{ // TCS
3859			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
3860			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3861			program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3862										 glsl_tes, NULL, NULL);
3863			program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3864										glsl_tes, NULL, NULL);
3865		}
3866		else if (m_stage == 2)
3867		{ // TES
3868			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3869			program_store =
3870				BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3871			program_load =
3872				BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3873		}
3874		else if (m_stage == 3)
3875		{ // GS
3876			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3877			program_store =
3878				BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3879			program_load =
3880				BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3881		}
3882		else if (m_stage == 4)
3883		{ // CS
3884			{
3885				std::string		  source = GenStoreShader(m_stage, internalformat, write_value);
3886				const char* const src	= source.c_str();
3887				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3888				glShaderSource(sh, 1, &src, NULL);
3889				glCompileShader(sh);
3890				program_store = glCreateProgram();
3891				glAttachShader(program_store, sh);
3892				glLinkProgram(program_store);
3893				glDeleteShader(sh);
3894			}
3895			{
3896				std::string		  source = GenLoadShader(m_stage, internalformat, expected_value);
3897				const char* const src	= source.c_str();
3898				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3899				glShaderSource(sh, 1, &src, NULL);
3900				glCompileShader(sh);
3901				program_load = glCreateProgram();
3902				glAttachShader(program_load, sh);
3903				glLinkProgram(program_load);
3904				glDeleteShader(sh);
3905			}
3906		}
3907		GLuint textures[kTargets], texture_result;
3908		glGenTextures(kTargets, textures);
3909		glGenTextures(1, &texture_result);
3910
3911		glBindTexture(GL_TEXTURE_2D, texture_result);
3912		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3913		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3914		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3915
3916		for (int i = 0; i < kTargets; ++i)
3917		{
3918			glBindTexture(targets[i], textures[i]);
3919			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3920			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3921
3922			if (targets[i] == GL_TEXTURE_1D)
3923			{
3924				glTexStorage1D(targets[i], 1, internalformat, 1);
3925			}
3926			else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3927			{
3928				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3929			}
3930			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3931			{
3932				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3933			}
3934			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3935			{
3936				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3937			}
3938			else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3939			{
3940				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3941			}
3942			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3943			{
3944				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3945			}
3946		}
3947		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3948		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3949		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3950		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3951		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3952		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3953		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3954		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3955
3956		glUseProgram(program_store);
3957		glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
3958		glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
3959		glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
3960		glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
3961		glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
3962		glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
3963		glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
3964		glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
3965
3966		glBindVertexArray(m_vao);
3967		if (m_stage == 1 || m_stage == 2)
3968		{ // TCS or TES
3969			glPatchParameteri(GL_PATCH_VERTICES, 1);
3970			glDrawArrays(GL_PATCHES, 0, 1);
3971			glPatchParameteri(GL_PATCH_VERTICES, 3);
3972		}
3973		else if (m_stage == 4)
3974		{ // CS
3975			glDispatchCompute(1, 1, 1);
3976		}
3977		else
3978		{
3979			glDrawArrays(GL_POINTS, 0, 1);
3980		}
3981
3982		bool status = true;
3983		for (int i = 0; i < kTargets; ++i)
3984		{
3985			glBindTexture(targets[i], textures[i]);
3986			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
3987
3988			if (targets[i] == GL_TEXTURE_CUBE_MAP)
3989			{
3990				for (int face = 0; face < 6; ++face)
3991				{
3992					T data;
3993					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
3994					if (!Equal(data, expected_value, internalformat))
3995					{
3996						status = false;
3997						m_context.getTestContext().getLog()
3998							<< tcu::TestLog::Message << "Value is: " << ToString(data)
3999							<< ". Value should be: " << ToString(expected_value)
4000							<< ". Format is: " << FormatEnumToString(internalformat)
4001							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4002							<< tcu::TestLog::EndMessage;
4003					}
4004				}
4005			}
4006			else
4007			{
4008				T data[12];
4009				memset(&data[0], 0, sizeof(data));
4010				glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4011
4012				int count = 1;
4013				if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4014					count = 2;
4015				else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4016					count = 12;
4017				else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4018					count = 2;
4019
4020				for (int j = 0; j < count; ++j)
4021				{
4022					if (!Equal(data[j], expected_value, internalformat))
4023					{
4024						status = false;
4025						m_context.getTestContext().getLog()
4026							<< tcu::TestLog::Message << "Value is: " << ToString(data[j])
4027							<< ". Value should be: " << ToString(expected_value)
4028							<< ". Format is: " << FormatEnumToString(internalformat)
4029							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4030							<< tcu::TestLog::EndMessage;
4031					}
4032				}
4033			}
4034		}
4035		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4036		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4037		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4038		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4039		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4040		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4041		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4042		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4043
4044		glUseProgram(program_load);
4045		glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4046		glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4047		glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4048		glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4049		glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4050		glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4051		glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4052		glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4053
4054		if (m_stage == 1 || m_stage == 2)
4055		{ // TCS or TES
4056			glPatchParameteri(GL_PATCH_VERTICES, 1);
4057			glDrawArrays(GL_PATCHES, 0, 1);
4058			glPatchParameteri(GL_PATCH_VERTICES, 3);
4059		}
4060		else if (m_stage == 4)
4061		{ // CS
4062			glDispatchCompute(1, 1, 1);
4063		}
4064		else
4065		{
4066			glDrawArrays(GL_POINTS, 0, 1);
4067		}
4068		{
4069			vec4 color;
4070			glBindTexture(GL_TEXTURE_2D, texture_result);
4071			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4072			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4073			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4074			{
4075				status = false;
4076				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4077													<< ". Format is: " << FormatEnumToString(internalformat)
4078													<< ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4079			}
4080		}
4081		glUseProgram(0);
4082		glDeleteProgram(program_store);
4083		glDeleteProgram(program_load);
4084		glDeleteTextures(kTargets, textures);
4085		glDeleteTextures(1, &texture_result);
4086		return status;
4087	}
4088
4089	template <typename T>
4090	std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4091	{
4092		std::ostringstream os;
4093		os << "#version 420 core";
4094		if (stage == 4)
4095		{ // CS
4096			os << NL "#extension GL_ARB_compute_shader : require";
4097		}
4098		os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4099		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4100		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4101		   << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4102		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4103		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4104		   << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4105		   << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4106		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4107		   << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4108		   << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4109		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4110		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4111		if (stage == 0)
4112		{ // VS
4113			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4114		}
4115		else if (stage == 1)
4116		{ // TCS
4117			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4118					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4119					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4120					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4121		}
4122		else if (stage == 2)
4123		{ // TES
4124			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4125					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4126		}
4127		else if (stage == 3)
4128		{ // GS
4129			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4130					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4131		}
4132		else if (stage == 4)
4133		{ // CS
4134			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4135					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4136		}
4137		os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4138				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4139				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4140				 "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4141				 "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4142				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4143				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4144				 "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4145				 "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4146				 "  for (int i = 0; i < 6; ++i) {" NL
4147				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4148				 "  for (int i = 0; i < 6; ++i) {" NL
4149				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4150		return os.str();
4151	}
4152
4153	template <typename T>
4154	std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4155	{
4156		std::ostringstream os;
4157		os << "#version 420 core";
4158		if (stage == 4)
4159		{ // CS
4160			os << NL "#extension GL_ARB_compute_shader : require";
4161		}
4162		os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4163		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4164		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4165		   << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4166		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4167		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4168		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4169		   << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4170		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4171		   << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4172			  "uniform "
4173		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4174		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4175		if (stage == 0)
4176		{ // VS
4177			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4178		}
4179		else if (stage == 1)
4180		{ // TCS
4181			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4182					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4183					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4184					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4185		}
4186		else if (stage == 2)
4187		{ // TES
4188			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4189					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4190		}
4191		else if (stage == 3)
4192		{ // GS
4193			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4194					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4195		}
4196		else if (stage == 4)
4197		{ // CS
4198			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4199					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4200		}
4201		os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4202		   << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4203			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4204			  "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4205			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4206			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4207			  "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4208			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4209			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4210			  "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4211			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4212			  "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4213			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4214		return os.str();
4215	}
4216
4217protected:
4218	long RunStage(int stage)
4219	{
4220		if (!SupportedInStage(stage, 8))
4221			return NOT_SUPPORTED;
4222
4223		glEnable(GL_RASTERIZER_DISCARD);
4224		m_stage = stage;
4225
4226		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4227			return ERROR;
4228		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4229			return ERROR;
4230		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4231			return ERROR;
4232
4233		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4234			return ERROR;
4235		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4236			return ERROR;
4237		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4238			return ERROR;
4239
4240		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4241			return ERROR;
4242		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4243			return ERROR;
4244		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4245			return ERROR;
4246
4247		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4248			return ERROR;
4249
4250		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4251			return ERROR;
4252		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4253			return ERROR;
4254		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4255			return ERROR;
4256
4257		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4258			return ERROR;
4259		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4260			return ERROR;
4261		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4262			return ERROR;
4263
4264		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4265			return ERROR;
4266		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4267			return ERROR;
4268		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4269			return ERROR;
4270		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4271			return ERROR;
4272
4273		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4274			return ERROR;
4275		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4276			return ERROR;
4277		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4278			return ERROR;
4279
4280		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4281			return ERROR;
4282		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4283			return ERROR;
4284		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4285			return ERROR;
4286
4287		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4288			return ERROR;
4289		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4290			return ERROR;
4291		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4292			return ERROR;
4293		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4294			return ERROR;
4295
4296		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4297			return ERROR;
4298		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4299			return ERROR;
4300		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4301			return ERROR;
4302
4303		//
4304		{
4305			if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4306				return ERROR;
4307			if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4308				return ERROR;
4309			if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4310				return ERROR;
4311
4312			if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4313				return ERROR;
4314			if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4315				return ERROR;
4316			if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4317				return ERROR;
4318		}
4319		return NO_ERROR;
4320	}
4321};
4322//-----------------------------------------------------------------------------
4323// AtomicMachine
4324//-----------------------------------------------------------------------------
4325class AtomicMachine : public ShaderImageLoadStoreBase
4326{
4327	GLuint m_vao;
4328
4329	virtual long Setup()
4330	{
4331		glEnable(GL_RASTERIZER_DISCARD);
4332		glGenVertexArrays(1, &m_vao);
4333		return NO_ERROR;
4334	}
4335
4336	virtual long Cleanup()
4337	{
4338		glDisable(GL_RASTERIZER_DISCARD);
4339		glDeleteVertexArrays(1, &m_vao);
4340		return NO_ERROR;
4341	}
4342
4343	template <typename T>
4344	bool Atomic(int stage, GLenum internalformat)
4345	{
4346		GLuint program = 0;
4347		if (stage == 0)
4348		{ // VS
4349			program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4350		}
4351		else if (stage == 1)
4352		{ // TCS
4353			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
4354			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4355			program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4356		}
4357		else if (stage == 2)
4358		{ // TES
4359			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4360			program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4361		}
4362		else if (stage == 3)
4363		{ // GS
4364			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4365			program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4366		}
4367		else if (stage == 4)
4368		{ // CS
4369			std::string		  source = GenShader<T>(stage, internalformat);
4370			const char* const src	= source.c_str();
4371			GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
4372			glShaderSource(sh, 1, &src, NULL);
4373			glCompileShader(sh);
4374			program = glCreateProgram();
4375			glAttachShader(program, sh);
4376			glLinkProgram(program);
4377			glDeleteShader(sh);
4378		}
4379		GLuint texture_result;
4380		glGenTextures(1, &texture_result);
4381		glBindTexture(GL_TEXTURE_2D, texture_result);
4382		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4383		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4384		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4385
4386		const GLenum targets[] = { GL_TEXTURE_2D,	 GL_TEXTURE_3D,	   GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4387								   GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4388		const int kTargets = sizeof(targets) / sizeof(targets[0]);
4389
4390		GLuint textures[kTargets];
4391		GLuint buffer;
4392		glGenTextures(kTargets, textures);
4393		glGenBuffers(1, &buffer);
4394
4395		for (int i = 0; i < kTargets; ++i)
4396		{
4397			glBindTexture(targets[i], textures[i]);
4398			if (targets[i] != GL_TEXTURE_BUFFER)
4399			{
4400				glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4401				glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4402			}
4403			if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4404			{
4405				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4406			}
4407			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4408			{
4409				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4410			}
4411			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4412			{
4413				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4414			}
4415			else if (targets[i] == GL_TEXTURE_BUFFER)
4416			{
4417				glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4418				glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4419				glBindBuffer(GL_TEXTURE_BUFFER, 0);
4420				glTexBuffer(targets[i], internalformat, buffer);
4421			}
4422			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4423			{
4424				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4425			}
4426		}
4427		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4428		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4429		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4430		glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4431		glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4432		glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4433		glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4434		glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4435
4436		glUseProgram(program);
4437		glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4438		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4439		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4440		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4441		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4442		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4443		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4444		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4445
4446		glBindVertexArray(m_vao);
4447		if (stage == 1 || stage == 2)
4448		{ // TCS or TES
4449			glPatchParameteri(GL_PATCH_VERTICES, 1);
4450			glDrawArrays(GL_PATCHES, 0, 1);
4451			glPatchParameteri(GL_PATCH_VERTICES, 3);
4452		}
4453		else if (stage == 4)
4454		{ // CS
4455			glDispatchCompute(1, 1, 1);
4456		}
4457		else
4458		{
4459			glDrawArrays(GL_POINTS, 0, 1);
4460		}
4461
4462		bool status = true;
4463		{
4464			vec4 color;
4465			glBindTexture(GL_TEXTURE_2D, texture_result);
4466			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4467			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4468			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4469			{
4470				status = false;
4471				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4472													<< ". Format is: " << FormatEnumToString(internalformat)
4473													<< ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4474			}
4475		}
4476		glUseProgram(0);
4477		glDeleteProgram(program);
4478		glDeleteTextures(7, textures);
4479		glDeleteTextures(1, &texture_result);
4480		glDeleteBuffers(1, &buffer);
4481		return status;
4482	}
4483
4484	template <typename T>
4485	std::string GenShader(int stage, GLenum internalformat)
4486	{
4487		std::ostringstream os;
4488		os << "#version 420 core";
4489		if (stage == 4)
4490		{ // CS
4491			os << NL "#extension GL_ARB_compute_shader : require";
4492		}
4493		os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4494		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4495		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4496		   << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4497		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4498		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4499		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4500		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4501		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4502		   << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4503			  "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4504		if (stage == 0)
4505		{ // VS
4506			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4507		}
4508		else if (stage == 1)
4509		{ // TCS
4510			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4511					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4512					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4513					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4514		}
4515		else if (stage == 2)
4516		{ // TES
4517			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4518					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4519		}
4520		else if (stage == 3)
4521		{ // GS
4522			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4523					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4524		}
4525		else if (stage == 4)
4526		{ // CS
4527			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4528					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4529		}
4530		os << NL
4531			"  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4532			"  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4533			"  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4534			"  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4535			"  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4536			"  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4537			"  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4538			"  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4539			"  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4540			"  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4541
4542			NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4543			"  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4544			"  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4545			"  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4546			"  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4547			"  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4548			"  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4549			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4550			"  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4551			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4552
4553			NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4554			"  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4555			"  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4556			"  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4557			"  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4558			"  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4559			"  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4560			"  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4561			"  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4562			"1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4563
4564			NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4565			"ivec3(coord, 0), g_value[2]) != 0) "
4566			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4567			"  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4568			"  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4569			"  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4570			"  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4571			"  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4572			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4573			"  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4574			"0.0, 1.0);" NL
4575			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4576
4577			NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4578			"  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4579			"  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580			"  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581			"  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582			"  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583			"  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584			"  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4585			"1.0);" NL
4586			"  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587			"  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4588
4589			NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4590			"  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591			"  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592			"  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4593			"1.0);" NL
4594			"  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595			"  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596			"  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4598			"1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4599			"0.0, 0.0, 1.0);" NL
4600			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4601
4602			NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4603			"  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604			"  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605			"  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606			"  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607			"  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608			"  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4609			"1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4610			"0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4611			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4612			"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4613
4614			NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4615		return os.str();
4616	}
4617
4618protected:
4619	long RunStage(int stage)
4620	{
4621		if (!SupportedInStage(stage, 8))
4622			return NOT_SUPPORTED;
4623		if (!Atomic<GLint>(stage, GL_R32I))
4624			return ERROR;
4625		if (!Atomic<GLuint>(stage, GL_R32UI))
4626			return ERROR;
4627		return NO_ERROR;
4628	}
4629};
4630//-----------------------------------------------------------------------------
4631// 1.3.4 BasicAllTargetsLoadStoreVS
4632//-----------------------------------------------------------------------------
4633class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4634{
4635	virtual long Run()
4636	{
4637		return RunStage(0);
4638	}
4639};
4640//-----------------------------------------------------------------------------
4641// 1.3.5 BasicAllTargetsLoadStoreTCS
4642//-----------------------------------------------------------------------------
4643class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4644{
4645	virtual long Run()
4646	{
4647		return RunStage(1);
4648	}
4649};
4650//-----------------------------------------------------------------------------
4651// 1.3.6 BasicAllTargetsLoadStoreTES
4652//-----------------------------------------------------------------------------
4653class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4654{
4655	virtual long Run()
4656	{
4657		return RunStage(2);
4658	}
4659};
4660//-----------------------------------------------------------------------------
4661// 1.3.7 BasicAllTargetsLoadStoreGS
4662//-----------------------------------------------------------------------------
4663class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4664{
4665	virtual long Run()
4666	{
4667		return RunStage(3);
4668	}
4669};
4670//-----------------------------------------------------------------------------
4671// 1.3.8 BasicAllTargetsLoadStoreCS
4672//-----------------------------------------------------------------------------
4673class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4674{
4675	virtual long Run()
4676	{
4677		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4678		{
4679			m_context.getTestContext().getLog()
4680				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4681				<< tcu::TestLog::EndMessage;
4682			return NO_ERROR;
4683		}
4684
4685		return RunStage(4);
4686	}
4687};
4688//-----------------------------------------------------------------------------
4689// 1.3.9 BasicAllTargetsAtomicVS
4690//-----------------------------------------------------------------------------
4691class BasicAllTargetsAtomicVS : public AtomicMachine
4692{
4693	virtual long Run()
4694	{
4695		return RunStage(0);
4696	}
4697};
4698//-----------------------------------------------------------------------------
4699// 1.3.10 BasicAllTargetsAtomicTCS
4700//-----------------------------------------------------------------------------
4701class BasicAllTargetsAtomicTCS : public AtomicMachine
4702{
4703	virtual long Run()
4704	{
4705		return RunStage(1);
4706	}
4707};
4708//-----------------------------------------------------------------------------
4709// 1.3.11 BasicAllTargetsAtomicTES
4710//-----------------------------------------------------------------------------
4711class BasicAllTargetsAtomicTES : public AtomicMachine
4712{
4713	virtual long Run()
4714	{
4715		return RunStage(2);
4716	}
4717};
4718//-----------------------------------------------------------------------------
4719// 1.3.12 BasicAllTargetsAtomicGS
4720//-----------------------------------------------------------------------------
4721class BasicAllTargetsAtomicGS : public AtomicMachine
4722{
4723	virtual long Run()
4724	{
4725		return RunStage(3);
4726	}
4727};
4728//-----------------------------------------------------------------------------
4729// 1.3.13 BasicAllTargetsAtomicCS
4730//-----------------------------------------------------------------------------
4731class BasicAllTargetsAtomicCS : public AtomicMachine
4732{
4733	virtual long Run()
4734	{
4735		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4736		{
4737			m_context.getTestContext().getLog()
4738				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4739				<< tcu::TestLog::EndMessage;
4740			return NO_ERROR;
4741		}
4742
4743		return RunStage(4);
4744	}
4745};
4746//-----------------------------------------------------------------------------
4747// 1.4.1 BasicGLSLMisc
4748//-----------------------------------------------------------------------------
4749class BasicGLSLMisc : public ShaderImageLoadStoreBase
4750{
4751	GLuint m_texture;
4752	GLuint m_program;
4753	GLuint m_vao, m_vbo;
4754
4755	virtual long Setup()
4756	{
4757		m_texture = 0;
4758		m_program = 0;
4759		m_vao = m_vbo = 0;
4760		return NO_ERROR;
4761	}
4762
4763	virtual long Run()
4764	{
4765		const int		  kSize = 32;
4766		std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4767
4768		glGenTextures(1, &m_texture);
4769		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4770		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4771		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4772		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4773
4774		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4775							 "  gl_Position = i_position;" NL "}";
4776		const char* src_fs =
4777			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4778			"layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4779			"layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4780			"void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4781			"  imageStore(g_image_layer0, coord, vec4(1.0));" NL "  memoryBarrier();" NL
4782			"  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4783			"  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4784			"  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4785		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4786
4787		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4788
4789		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4790		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4791
4792		glClear(GL_COLOR_BUFFER_BIT);
4793		glViewport(0, 0, kSize, kSize);
4794
4795		glUseProgram(m_program);
4796		glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4797		glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4798
4799		glBindVertexArray(m_vao);
4800		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4801
4802		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4803		{
4804			return ERROR;
4805		}
4806		return NO_ERROR;
4807	}
4808
4809	virtual long Cleanup()
4810	{
4811		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4812		glDeleteTextures(1, &m_texture);
4813		glDeleteVertexArrays(1, &m_vao);
4814		glDeleteBuffers(1, &m_vbo);
4815		glUseProgram(0);
4816		glDeleteProgram(m_program);
4817		return NO_ERROR;
4818	}
4819};
4820//-----------------------------------------------------------------------------
4821// 1.4.2 BasicGLSLEarlyFragTests
4822//-----------------------------------------------------------------------------
4823class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4824{
4825	GLuint m_texture[2];
4826	GLuint m_program[2];
4827	GLuint m_vao, m_vbo;
4828
4829	virtual long Setup()
4830	{
4831		m_texture[0] = m_texture[1] = 0;
4832		m_program[0] = m_program[1] = 0;
4833		m_vao = m_vbo = 0;
4834		return NO_ERROR;
4835	}
4836
4837	virtual long Run()
4838	{
4839		int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4840
4841		const int		  kSize = 32;
4842		std::vector<vec4> data(kSize * kSize);
4843
4844		glGenTextures(2, m_texture);
4845		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4846		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4847		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4848		glBindTexture(GL_TEXTURE_2D, 0);
4849
4850		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4851		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4852		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4853		glBindTexture(GL_TEXTURE_2D, 0);
4854
4855		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4856							  "  gl_Position = i_position;" NL "}";
4857		const char* glsl_early_frag_tests_fs =
4858			"#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4859			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4860			"  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4861			"  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4862		const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4863							  "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4864							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4865							  "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4866		m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4867		m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4868
4869		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4870
4871		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4872		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4873
4874		glViewport(0, 0, kSize, kSize);
4875		glBindVertexArray(m_vao);
4876
4877		glEnable(GL_DEPTH_TEST);
4878		glClearColor(0.0, 1.0f, 0.0, 1.0f);
4879		glClearDepthf(0.0f);
4880
4881		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4882		glUseProgram(m_program[0]);
4883		glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4884
4885		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4886
4887		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4888		glUseProgram(m_program[1]);
4889		glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4890		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4891
4892		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4893		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4894		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4895		for (int i = 0; i < kSize * kSize; ++i)
4896		{
4897			if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4898				return ERROR;
4899		}
4900
4901		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4902		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4903		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4904		for (int i = 0; i < kSize * kSize; ++i)
4905		{
4906			if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4907				return ERROR;
4908		}
4909
4910		return NO_ERROR;
4911	}
4912
4913	virtual long Cleanup()
4914	{
4915		glDisable(GL_DEPTH_TEST);
4916		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4917		glClearDepthf(1.0f);
4918		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4919		glDeleteTextures(2, m_texture);
4920		glDeleteVertexArrays(1, &m_vao);
4921		glDeleteBuffers(1, &m_vbo);
4922		glUseProgram(0);
4923		glDeleteProgram(m_program[0]);
4924		glDeleteProgram(m_program[1]);
4925		return NO_ERROR;
4926	}
4927};
4928//-----------------------------------------------------------------------------
4929// 1.4.3 BasicGLSLConst
4930//-----------------------------------------------------------------------------
4931class BasicGLSLConst : public ShaderImageLoadStoreBase
4932{
4933	GLuint m_program;
4934	GLuint m_vao, m_vbo;
4935
4936	virtual long Setup()
4937	{
4938		m_program = 0;
4939		m_vao = m_vbo = 0;
4940		return NO_ERROR;
4941	}
4942
4943	virtual long Run()
4944	{
4945		bool isAtLeast44Context =
4946			glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4947
4948		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4949							 "  gl_Position = i_position;" NL "}";
4950		std::ostringstream src_fs;
4951		src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4952		src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
4953					 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
4954					 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
4955					 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
4956					 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
4957					 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
4958					 "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
4959		if (isAtLeast44Context)
4960			src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
4961						 "vec4(0.2, 0.0, 0.0, 0.2);";
4962		else
4963			src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
4964						 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
4965		src_fs << NL
4966			"  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
4967			"  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
4968			"  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
4969			"0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
4970			"0.0, 0.0, 0.6);" NL
4971			"  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
4972			"  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
4973			"  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
4974
4975		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
4976		glUseProgram(m_program);
4977
4978		GLint i;
4979		glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
4980		glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
4981
4982		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
4983		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
4984
4985		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
4986		glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
4987
4988		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
4989		glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
4990
4991		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
4992		glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
4993
4994		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
4995		glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
4996
4997		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
4998		glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
4999
5000		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5001		glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5002
5003		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5004		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5005
5006		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5007
5008		glClear(GL_COLOR_BUFFER_BIT);
5009		glBindVertexArray(m_vao);
5010		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5011
5012		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5013		{
5014			return ERROR;
5015		}
5016		return NO_ERROR;
5017	}
5018
5019	virtual long Cleanup()
5020	{
5021		glDeleteVertexArrays(1, &m_vao);
5022		glDeleteBuffers(1, &m_vbo);
5023		glUseProgram(0);
5024		glDeleteProgram(m_program);
5025		return NO_ERROR;
5026	}
5027};
5028//-----------------------------------------------------------------------------
5029// 2.1.1 AdvancedSyncImageAccess
5030//-----------------------------------------------------------------------------
5031class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5032{
5033	GLuint m_buffer;
5034	GLuint m_buffer_tex;
5035	GLuint m_store_program;
5036	GLuint m_draw_program;
5037	GLuint m_attribless_vao;
5038
5039	virtual long Setup()
5040	{
5041		m_buffer		 = 0;
5042		m_buffer_tex	 = 0;
5043		m_store_program  = 0;
5044		m_draw_program   = 0;
5045		m_attribless_vao = 0;
5046		return NO_ERROR;
5047	}
5048
5049	virtual long Run()
5050	{
5051		if (!SupportedInVS(1))
5052			return NOT_SUPPORTED;
5053		const char* const glsl_store_vs =
5054			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5055			"  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5056			"  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5057		const char* const glsl_draw_vs =
5058			"#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5059			"uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5060			"  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5061			"  if (pi != ps) vs_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  else vs_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5062			"  gl_Position = pi;" NL "}";
5063		const char* const glsl_draw_fs =
5064			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5065			"  o_color = vs_color;" NL "}";
5066		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5067		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5068
5069		glGenVertexArrays(1, &m_attribless_vao);
5070		glBindVertexArray(m_attribless_vao);
5071
5072		glGenBuffers(1, &m_buffer);
5073		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5074		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5075		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5076
5077		glGenTextures(1, &m_buffer_tex);
5078		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5079		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5080
5081		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5082
5083		glEnable(GL_RASTERIZER_DISCARD);
5084		glUseProgram(m_store_program);
5085		glDrawArrays(GL_POINTS, 0, 4);
5086
5087		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5088
5089		glDisable(GL_RASTERIZER_DISCARD);
5090		glClear(GL_COLOR_BUFFER_BIT);
5091		glUseProgram(m_draw_program);
5092		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5093
5094		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5095		{
5096			return ERROR;
5097		}
5098		return NO_ERROR;
5099	}
5100
5101	virtual long Cleanup()
5102	{
5103		glUseProgram(0);
5104		glDeleteBuffers(1, &m_buffer);
5105		glDeleteTextures(1, &m_buffer_tex);
5106		glDeleteProgram(m_store_program);
5107		glDeleteProgram(m_draw_program);
5108		glDeleteVertexArrays(1, &m_attribless_vao);
5109		return NO_ERROR;
5110	}
5111};
5112//-----------------------------------------------------------------------------
5113// 2.1.2 AdvancedSyncVertexArray
5114//-----------------------------------------------------------------------------
5115class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5116{
5117	GLuint m_position_buffer;
5118	GLuint m_color_buffer;
5119	GLuint m_element_buffer;
5120	GLuint m_position_buffer_tex;
5121	GLuint m_color_buffer_tex;
5122	GLuint m_element_buffer_tex;
5123	GLuint m_store_program;
5124	GLuint m_draw_program;
5125	GLuint m_attribless_vao;
5126	GLuint m_draw_vao;
5127
5128	virtual long Setup()
5129	{
5130		m_position_buffer	 = 0;
5131		m_color_buffer		  = 0;
5132		m_element_buffer	  = 0;
5133		m_position_buffer_tex = 0;
5134		m_color_buffer_tex	= 0;
5135		m_element_buffer_tex  = 0;
5136		m_store_program		  = 0;
5137		m_draw_program		  = 0;
5138		m_attribless_vao	  = 0;
5139		m_draw_vao			  = 0;
5140		return NO_ERROR;
5141	}
5142
5143	virtual long Run()
5144	{
5145		if (!SupportedInVS(3))
5146			return NOT_SUPPORTED;
5147		const char* const glsl_store_vs =
5148			"#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5149			"layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5150			"layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5151			"void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5152			"  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5153			"  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5154			"  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5155		const char* const glsl_draw_vs =
5156			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5157			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5158			"  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5159		const char* const glsl_draw_fs =
5160			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5161			"  o_color = vs_color;" NL "}";
5162		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5163		glUseProgram(m_store_program);
5164		glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5165		glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5166		glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5167		glUseProgram(0);
5168
5169		m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5170
5171		glGenBuffers(1, &m_position_buffer);
5172		glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5173		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5174		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5175
5176		glGenBuffers(1, &m_color_buffer);
5177		glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5178		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5179		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5180
5181		glGenBuffers(1, &m_element_buffer);
5182		glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5183		glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5184		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5185
5186		glGenTextures(1, &m_position_buffer_tex);
5187		glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5188		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5189		glBindTexture(GL_TEXTURE_BUFFER, 0);
5190
5191		glGenTextures(1, &m_color_buffer_tex);
5192		glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5193		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5194		glBindTexture(GL_TEXTURE_BUFFER, 0);
5195
5196		glGenTextures(1, &m_element_buffer_tex);
5197		glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5198		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5199		glBindTexture(GL_TEXTURE_BUFFER, 0);
5200
5201		glGenVertexArrays(1, &m_attribless_vao);
5202
5203		glGenVertexArrays(1, &m_draw_vao);
5204		glBindVertexArray(m_draw_vao);
5205		glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5206		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5207		glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5208		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5209		glBindBuffer(GL_ARRAY_BUFFER, 0);
5210		glEnableVertexAttribArray(0);
5211		glEnableVertexAttribArray(1);
5212		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5213		glBindVertexArray(0);
5214
5215		glEnable(GL_RASTERIZER_DISCARD);
5216		glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5217		glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5218		glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5219		glUseProgram(m_store_program);
5220		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5221		glBindVertexArray(m_attribless_vao);
5222		glDrawArrays(GL_POINTS, 0, 4);
5223
5224		glDisable(GL_RASTERIZER_DISCARD);
5225		glClear(GL_COLOR_BUFFER_BIT);
5226		glUseProgram(m_draw_program);
5227		glBindVertexArray(m_draw_vao);
5228		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5229		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5230
5231		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5232		{
5233			return ERROR;
5234		}
5235
5236		glEnable(GL_RASTERIZER_DISCARD);
5237		glUseProgram(m_store_program);
5238		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5239		glBindVertexArray(m_attribless_vao);
5240		glDrawArrays(GL_POINTS, 0, 4);
5241
5242		glDisable(GL_RASTERIZER_DISCARD);
5243		glClear(GL_COLOR_BUFFER_BIT);
5244		glUseProgram(m_draw_program);
5245		glBindVertexArray(m_draw_vao);
5246		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5247		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5248
5249		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5250		{
5251			return ERROR;
5252		}
5253		return NO_ERROR;
5254	}
5255
5256	virtual long Cleanup()
5257	{
5258		glDisable(GL_RASTERIZER_DISCARD);
5259		glUseProgram(0);
5260		glDeleteBuffers(1, &m_position_buffer);
5261		glDeleteBuffers(1, &m_color_buffer);
5262		glDeleteBuffers(1, &m_element_buffer);
5263		glDeleteTextures(1, &m_position_buffer_tex);
5264		glDeleteTextures(1, &m_color_buffer_tex);
5265		glDeleteTextures(1, &m_element_buffer_tex);
5266		glDeleteProgram(m_store_program);
5267		glDeleteProgram(m_draw_program);
5268		glDeleteVertexArrays(1, &m_attribless_vao);
5269		glDeleteVertexArrays(1, &m_draw_vao);
5270		return NO_ERROR;
5271	}
5272};
5273
5274//-----------------------------------------------------------------------------
5275// 2.1.4 AdvancedSyncDrawIndirect
5276//-----------------------------------------------------------------------------
5277class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5278{
5279	GLuint m_draw_command_buffer;
5280	GLuint m_draw_command_buffer_tex;
5281	GLuint m_store_program;
5282	GLuint m_draw_program;
5283	GLuint m_attribless_vao;
5284	GLuint m_draw_vao;
5285	GLuint m_draw_vbo;
5286
5287	virtual long Setup()
5288	{
5289		m_draw_command_buffer	 = 0;
5290		m_draw_command_buffer_tex = 0;
5291		m_store_program			  = 0;
5292		m_draw_program			  = 0;
5293		m_attribless_vao		  = 0;
5294		m_draw_vao				  = 0;
5295		m_draw_vbo				  = 0;
5296		return NO_ERROR;
5297	}
5298
5299	virtual long Run()
5300	{
5301		if (!SupportedInVS(1))
5302			return NOT_SUPPORTED;
5303		const char* const glsl_store_vs =
5304			"#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5305			"  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5306		const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5307										 "void main() {" NL "  gl_Position = i_position;" NL "}";
5308		const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5309										 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5310		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5311		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5312
5313		glGenBuffers(1, &m_draw_command_buffer);
5314		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5315		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5316		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5317
5318		glGenTextures(1, &m_draw_command_buffer_tex);
5319		glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5320		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5321		glBindTexture(GL_TEXTURE_BUFFER, 0);
5322
5323		glGenVertexArrays(1, &m_attribless_vao);
5324		CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5325
5326		glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5327
5328		glEnable(GL_RASTERIZER_DISCARD);
5329		glUseProgram(m_store_program);
5330		glBindVertexArray(m_attribless_vao);
5331		glDrawArrays(GL_POINTS, 0, 1);
5332
5333		glDisable(GL_RASTERIZER_DISCARD);
5334		glClear(GL_COLOR_BUFFER_BIT);
5335		glUseProgram(m_draw_program);
5336		glBindVertexArray(m_draw_vao);
5337		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5338		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5339		glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5340
5341		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5342		{
5343			return ERROR;
5344		}
5345		return NO_ERROR;
5346	}
5347
5348	virtual long Cleanup()
5349	{
5350		glUseProgram(0);
5351		glDeleteBuffers(1, &m_draw_command_buffer);
5352		glDeleteTextures(1, &m_draw_command_buffer_tex);
5353		glDeleteProgram(m_store_program);
5354		glDeleteProgram(m_draw_program);
5355		glDeleteVertexArrays(1, &m_attribless_vao);
5356		glDeleteVertexArrays(1, &m_draw_vao);
5357		glDeleteBuffers(1, &m_draw_vbo);
5358		return NO_ERROR;
5359	}
5360};
5361//-----------------------------------------------------------------------------
5362// 2.1.5 AdvancedSyncTextureUpdate
5363//-----------------------------------------------------------------------------
5364class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5365{
5366	GLuint m_texture;
5367	GLuint m_store_program;
5368	GLuint m_draw_program;
5369	GLuint m_vao;
5370	GLuint m_vbo;
5371	GLuint m_pbo;
5372
5373	virtual long Setup()
5374	{
5375		m_texture		= 0;
5376		m_store_program = 0;
5377		m_draw_program  = 0;
5378		m_vao			= 0;
5379		m_vbo			= 0;
5380		m_pbo			= 0;
5381		return NO_ERROR;
5382	}
5383
5384	virtual long Run()
5385	{
5386		const char* const glsl_vs =
5387			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5388			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5389		const char* const glsl_store_fs =
5390			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5391			"  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5392		const char* const glsl_draw_fs =
5393			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5394			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5395		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5396		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5397
5398		std::vector<vec4> data(16 * 16, vec4(1.0f));
5399		glGenBuffers(1, &m_pbo);
5400		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5401		glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5402		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5403
5404		glGenTextures(1, &m_texture);
5405		glBindTexture(GL_TEXTURE_2D, m_texture);
5406		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5407		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5408		glBindTexture(GL_TEXTURE_2D, 0);
5409
5410		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5411
5412		glViewport(0, 0, 16, 16);
5413		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5414		glUseProgram(m_store_program);
5415		glBindVertexArray(m_vao);
5416		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5417
5418		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5419		glBindTexture(GL_TEXTURE_2D, m_texture);
5420		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5421		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5422		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5423
5424		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5425		glClear(GL_COLOR_BUFFER_BIT);
5426		glUseProgram(m_draw_program);
5427		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5428
5429		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5430		{
5431			return ERROR;
5432		}
5433		return NO_ERROR;
5434	}
5435
5436	virtual long Cleanup()
5437	{
5438		glUseProgram(0);
5439		glDeleteBuffers(1, &m_vbo);
5440		glDeleteBuffers(1, &m_pbo);
5441		glDeleteTextures(1, &m_texture);
5442		glDeleteProgram(m_store_program);
5443		glDeleteProgram(m_draw_program);
5444		glDeleteVertexArrays(1, &m_vao);
5445		return NO_ERROR;
5446	}
5447};
5448//-----------------------------------------------------------------------------
5449// 2.1.6 AdvancedSyncImageAccess2
5450//-----------------------------------------------------------------------------
5451class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5452{
5453	GLuint m_texture;
5454	GLuint m_store_program;
5455	GLuint m_draw_program;
5456	GLuint m_vao;
5457	GLuint m_vbo;
5458
5459	virtual long Setup()
5460	{
5461		m_texture		= 0;
5462		m_store_program = 0;
5463		m_draw_program  = 0;
5464		m_vao			= 0;
5465		m_vbo			= 0;
5466		return NO_ERROR;
5467	}
5468
5469	virtual long Run()
5470	{
5471		const char* const glsl_vs =
5472			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5473			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5474		const char* const glsl_store_fs =
5475			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5476			"  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5477		const char* const glsl_draw_fs =
5478			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5479			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5480		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5481		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5482
5483		glGenTextures(1, &m_texture);
5484		glBindTexture(GL_TEXTURE_2D, m_texture);
5485		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5486		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL);
5487		glBindTexture(GL_TEXTURE_2D, 0);
5488
5489		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5490
5491		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5492		glUseProgram(m_store_program);
5493		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5494		glBindVertexArray(m_vao);
5495		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5496
5497		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5498
5499		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5500		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5501
5502		glClear(GL_COLOR_BUFFER_BIT);
5503		glBindTexture(GL_TEXTURE_2D, m_texture);
5504		glUseProgram(m_draw_program);
5505		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5506
5507		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5508		{
5509			return ERROR;
5510		}
5511		return NO_ERROR;
5512	}
5513
5514	virtual long Cleanup()
5515	{
5516		glUseProgram(0);
5517		glDeleteBuffers(1, &m_vbo);
5518		glDeleteTextures(1, &m_texture);
5519		glDeleteProgram(m_store_program);
5520		glDeleteProgram(m_draw_program);
5521		glDeleteVertexArrays(1, &m_vao);
5522		return NO_ERROR;
5523	}
5524};
5525//-----------------------------------------------------------------------------
5526// 2.1.7 AdvancedSyncBufferUpdate
5527//-----------------------------------------------------------------------------
5528class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5529{
5530	GLuint m_buffer;
5531	GLuint m_buffer_tex;
5532	GLuint m_store_program;
5533	GLuint m_attribless_vao;
5534
5535	virtual long Setup()
5536	{
5537		m_buffer		 = 0;
5538		m_buffer_tex	 = 0;
5539		m_store_program  = 0;
5540		m_attribless_vao = 0;
5541		return NO_ERROR;
5542	}
5543
5544	virtual long Run()
5545	{
5546		if (!SupportedInVS(1))
5547			return NOT_SUPPORTED;
5548		const char* const glsl_store_vs =
5549			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5550			"  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5551		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5552
5553		glGenVertexArrays(1, &m_attribless_vao);
5554		glBindVertexArray(m_attribless_vao);
5555
5556		glGenBuffers(1, &m_buffer);
5557		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5558		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5559		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5560
5561		glGenTextures(1, &m_buffer_tex);
5562		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5563		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5564
5565		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5566
5567		glEnable(GL_RASTERIZER_DISCARD);
5568		glUseProgram(m_store_program);
5569		glDrawArrays(GL_POINTS, 0, 1000);
5570
5571		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5572
5573		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5574		vec4* ptr =
5575			reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5576		for (int i = 0; i < 1000; ++i)
5577		{
5578			if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5579			{
5580				m_context.getTestContext().getLog()
5581					<< tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5582				return ERROR;
5583			}
5584		}
5585		return NO_ERROR;
5586	}
5587
5588	virtual long Cleanup()
5589	{
5590		glDisable(GL_RASTERIZER_DISCARD);
5591		glUseProgram(0);
5592		glDeleteBuffers(1, &m_buffer);
5593		glDeleteTextures(1, &m_buffer_tex);
5594		glDeleteProgram(m_store_program);
5595		glDeleteVertexArrays(1, &m_attribless_vao);
5596		return NO_ERROR;
5597	}
5598};
5599//-----------------------------------------------------------------------------
5600// 2.2.1 AdvancedAllStagesOneImage
5601//-----------------------------------------------------------------------------
5602class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5603{
5604	GLuint m_program;
5605	GLuint m_vao;
5606	GLuint m_vbo;
5607	GLuint m_ebo;
5608	GLuint m_buffer;
5609	GLuint m_buffer_tex;
5610	GLuint m_texture;
5611
5612	virtual long Setup()
5613	{
5614		m_program	= 0;
5615		m_vao		 = 0;
5616		m_vbo		 = 0;
5617		m_ebo		 = 0;
5618		m_buffer	 = 0;
5619		m_buffer_tex = 0;
5620		m_texture	= 0;
5621		return NO_ERROR;
5622	}
5623
5624	virtual long Run()
5625	{
5626		if (!SupportedInGeomStages(2))
5627			return NOT_SUPPORTED;
5628		const char* const glsl_vs =
5629			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5630			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5631			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5632			"  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5633			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5634		const char* const glsl_tcs =
5635			"#version 420 core" NL "layout(vertices = 1) out;" NL
5636			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5637			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5638			"  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5639			"  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5640			"  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5641			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5642		const char* const glsl_tes =
5643			"#version 420 core" NL "layout(triangles, point_mode) in;" NL
5644			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5645			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5646			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5647			"  gl_Position = gl_in[0].gl_Position;" NL "}";
5648		const char* const glsl_gs =
5649			"#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5650			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5651			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5652			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5653			"  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5654		const char* const glsl_fs =
5655			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5656			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5657			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5658			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5659			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5660		m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5661		glUseProgram(m_program);
5662		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5663		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5664
5665		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5666
5667		GLint i32 = 0;
5668		glGenBuffers(1, &m_buffer);
5669		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5670		glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5671		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5672
5673		glGenTextures(1, &m_buffer_tex);
5674		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5675		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5676		glBindTexture(GL_TEXTURE_BUFFER, 0);
5677
5678		GLuint ui32 = 0;
5679		glGenTextures(1, &m_texture);
5680		glBindTexture(GL_TEXTURE_2D, m_texture);
5681		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5682		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5683		glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5684		glBindTexture(GL_TEXTURE_2D, 0);
5685
5686		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5687		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5688
5689		glBindVertexArray(m_vao);
5690		glPatchParameteri(GL_PATCH_VERTICES, 1);
5691
5692		glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5693		glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5694
5695		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5696		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5697		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5698		if (i32 < 20 || i32 > 50)
5699		{
5700			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5701												<< " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5702			return ERROR;
5703		}
5704
5705		glBindTexture(GL_TEXTURE_2D, m_texture);
5706		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5707		if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5708		{
5709			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5710												<< (2 * i32) << tcu::TestLog::EndMessage;
5711			return ERROR;
5712		}
5713
5714		return NO_ERROR;
5715	}
5716
5717	virtual long Cleanup()
5718	{
5719		glPatchParameteri(GL_PATCH_VERTICES, 3);
5720		glUseProgram(0);
5721		glDeleteBuffers(1, &m_buffer);
5722		glDeleteBuffers(1, &m_vbo);
5723		glDeleteBuffers(1, &m_ebo);
5724		glDeleteTextures(1, &m_buffer_tex);
5725		glDeleteTextures(1, &m_texture);
5726		glDeleteProgram(m_program);
5727		glDeleteVertexArrays(1, &m_vao);
5728		return NO_ERROR;
5729	}
5730};
5731//-----------------------------------------------------------------------------
5732// 2.3.1 AdvancedMemoryDependentInvocation
5733//-----------------------------------------------------------------------------
5734class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5735{
5736	GLuint m_buffer;
5737	GLuint m_buffer_tex;
5738	GLuint m_texture;
5739	GLuint m_program;
5740	GLuint m_vao;
5741	GLuint m_vbo;
5742
5743	virtual long Setup()
5744	{
5745		m_buffer	 = 0;
5746		m_buffer_tex = 0;
5747		m_texture	= 0;
5748		m_program	= 0;
5749		m_vao		 = 0;
5750		m_vbo		 = 0;
5751		return NO_ERROR;
5752	}
5753
5754	virtual long Run()
5755	{
5756		if (!SupportedInVS(2))
5757			return NOT_SUPPORTED;
5758		const char* const glsl_vs =
5759			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5760			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5761			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5762			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5763			"  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5764			"  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5765		const char* const glsl_fs =
5766			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5767			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5768			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5769			"  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5770			"  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5771		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5772		glUseProgram(m_program);
5773		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5774		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5775
5776		vec4 zero(0);
5777		glGenBuffers(1, &m_buffer);
5778		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5779		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5780		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5781
5782		glGenTextures(1, &m_buffer_tex);
5783		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5784		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5785		glBindTexture(GL_TEXTURE_BUFFER, 0);
5786
5787		glGenTextures(1, &m_texture);
5788		glBindTexture(GL_TEXTURE_2D, m_texture);
5789		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5790		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5791		glBindTexture(GL_TEXTURE_2D, 0);
5792
5793		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5794		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5795
5796		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5797
5798		glClear(GL_COLOR_BUFFER_BIT);
5799		glBindVertexArray(m_vao);
5800		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5801
5802		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5803		{
5804			return ERROR;
5805		}
5806		return NO_ERROR;
5807	}
5808
5809	virtual long Cleanup()
5810	{
5811		glUseProgram(0);
5812		glDeleteBuffers(1, &m_vbo);
5813		glDeleteBuffers(1, &m_buffer);
5814		glDeleteTextures(1, &m_texture);
5815		glDeleteTextures(1, &m_buffer_tex);
5816		glDeleteProgram(m_program);
5817		glDeleteVertexArrays(1, &m_vao);
5818		return NO_ERROR;
5819	}
5820};
5821//-----------------------------------------------------------------------------
5822// 2.3.2 AdvancedMemoryOrder
5823//-----------------------------------------------------------------------------
5824class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5825{
5826	GLuint m_buffer;
5827	GLuint m_buffer_tex;
5828	GLuint m_texture;
5829	GLuint m_program;
5830	GLuint m_vao;
5831	GLuint m_vbo;
5832
5833	virtual long Setup()
5834	{
5835		m_buffer	 = 0;
5836		m_buffer_tex = 0;
5837		m_texture	= 0;
5838		m_program	= 0;
5839		m_vao		 = 0;
5840		m_vbo		 = 0;
5841		return NO_ERROR;
5842	}
5843
5844	virtual long Run()
5845	{
5846		if (!SupportedInVS(1))
5847			return NOT_SUPPORTED;
5848		const char* const glsl_vs =
5849			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5850			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5851			"  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5852			"  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5853			"  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5854			"  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5855		const char* const glsl_fs =
5856			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5857			"layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5858			"  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5859			"    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5860			"    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5861			"}";
5862		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5863		glUseProgram(m_program);
5864		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5865		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5866
5867		glGenBuffers(1, &m_buffer);
5868		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5869		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5870		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5871
5872		glGenTextures(1, &m_buffer_tex);
5873		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5874		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5875		glBindTexture(GL_TEXTURE_BUFFER, 0);
5876
5877		std::vector<vec4> data(getWindowWidth() * getWindowHeight());
5878		glGenTextures(1, &m_texture);
5879		glBindTexture(GL_TEXTURE_2D, m_texture);
5880		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5881		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]);
5882		glBindTexture(GL_TEXTURE_2D, 0);
5883
5884		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5885		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5886
5887		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5888
5889		glClear(GL_COLOR_BUFFER_BIT);
5890		glBindVertexArray(m_vao);
5891		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5892
5893		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5894		{
5895			return ERROR;
5896		}
5897		return NO_ERROR;
5898	}
5899
5900	virtual long Cleanup()
5901	{
5902		glUseProgram(0);
5903		glDeleteBuffers(1, &m_vbo);
5904		glDeleteBuffers(1, &m_buffer);
5905		glDeleteTextures(1, &m_texture);
5906		glDeleteTextures(1, &m_buffer_tex);
5907		glDeleteProgram(m_program);
5908		glDeleteVertexArrays(1, &m_vao);
5909		return NO_ERROR;
5910	}
5911};
5912//-----------------------------------------------------------------------------
5913// 2.4.1 AdvancedSSOSimple
5914//-----------------------------------------------------------------------------
5915class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5916{
5917	GLuint m_texture;
5918	GLuint m_pipeline[2];
5919	GLuint m_vsp, m_fsp0, m_fsp1;
5920	GLuint m_vao, m_vbo;
5921
5922	virtual long Setup()
5923	{
5924		glGenTextures(1, &m_texture);
5925		glGenProgramPipelines(2, m_pipeline);
5926		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5927
5928		const char* const glsl_vs =
5929			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5930			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5931		const char* const glsl_fs0 =
5932			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5933			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5934			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
5935		const char* const glsl_fs1 =
5936			"#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5937			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5938			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
5939		m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5940		m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
5941		m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
5942
5943		return NO_ERROR;
5944	}
5945
5946	virtual long Run()
5947	{
5948		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
5949		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
5950		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
5951		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
5952
5953		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
5954		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
5955		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
5956		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
5957
5958		glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
5959		glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
5960
5961		glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
5962		glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
5963
5964		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
5965		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5966		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 8, 0, GL_RGBA, GL_FLOAT,
5967					 NULL);
5968
5969		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5970		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
5971		glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
5972		glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
5973		glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
5974		glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
5975		glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
5976		glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
5977
5978		glBindVertexArray(m_vao);
5979
5980		glBindProgramPipeline(m_pipeline[0]);
5981		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5982
5983		glBindProgramPipeline(m_pipeline[1]);
5984		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5985
5986		std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 8);
5987		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
5988
5989		for (int layer = 0; layer < 8; ++layer)
5990		{
5991			for (int h = 0; h < getWindowHeight(); ++h)
5992			{
5993				for (int w = 0; w < getWindowWidth(); ++w)
5994				{
5995					const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
5996					if (layer % 2)
5997					{
5998						if (!IsEqual(c, vec4(2.0f)))
5999						{
6000							return ERROR;
6001						}
6002					}
6003					else
6004					{
6005						if (!IsEqual(c, vec4(1.0f)))
6006						{
6007							return ERROR;
6008						}
6009					}
6010				}
6011			}
6012		}
6013		return NO_ERROR;
6014	}
6015
6016	virtual long Cleanup()
6017	{
6018		glDeleteBuffers(1, &m_vbo);
6019		glDeleteTextures(1, &m_texture);
6020		glDeleteProgram(m_vsp);
6021		glDeleteProgram(m_fsp0);
6022		glDeleteProgram(m_fsp1);
6023		glDeleteVertexArrays(1, &m_vao);
6024		glDeleteProgramPipelines(2, m_pipeline);
6025		return NO_ERROR;
6026	}
6027};
6028//-----------------------------------------------------------------------------
6029// 2.4.2 AdvancedSSOAtomicCounters
6030//-----------------------------------------------------------------------------
6031class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6032{
6033	GLuint m_buffer, m_buffer_tex;
6034	GLuint m_counter_buffer;
6035	GLuint m_transform_buffer;
6036	GLuint m_pipeline;
6037	GLuint m_vao, m_vbo;
6038	GLuint m_vsp, m_fsp;
6039
6040	virtual long Setup()
6041	{
6042		m_vao = 0;
6043		m_vbo = 0;
6044		m_vsp = 0;
6045		m_fsp = 0;
6046		glGenBuffers(1, &m_buffer);
6047		glGenTextures(1, &m_buffer_tex);
6048		glGenBuffers(1, &m_counter_buffer);
6049		glGenBuffers(1, &m_transform_buffer);
6050		glGenProgramPipelines(1, &m_pipeline);
6051		return NO_ERROR;
6052	}
6053
6054	virtual long Run()
6055	{
6056		if (!SupportedInVS(1))
6057			return NOT_SUPPORTED;
6058
6059		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6060		const char* const glsl_vs =
6061			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6062			"layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6063			"out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6064			"  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6065			"layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6066			"  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6067			"  const uint index = atomicCounterIncrement(g_counter);" NL
6068			"  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6069		const char* const glsl_fs =
6070			"#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6071			"layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6072		m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6073		m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6074
6075		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6076		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6077
6078		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6079		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6080
6081		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6082		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6083
6084		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6085		vec4 zero(0);
6086		glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6087
6088		glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6089		mat4 identity(1);
6090		glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6091
6092		glClear(GL_COLOR_BUFFER_BIT);
6093		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6094		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6095		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6096		glBindVertexArray(m_vao);
6097		glBindProgramPipeline(m_pipeline);
6098		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6099
6100		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6101		{
6102			return ERROR;
6103		}
6104
6105		std::vector<vec4> data(4);
6106		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6107		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6108
6109		for (int i = 0; i < 4; ++i)
6110		{
6111			if (!IsEqual(data[i], vec4(-1.0f, -1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, -1.0f, 0.0f, 1.0f)) &&
6112				!IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6113			{
6114				return ERROR;
6115			}
6116		}
6117
6118		return NO_ERROR;
6119	}
6120
6121	virtual long Cleanup()
6122	{
6123		glDeleteBuffers(1, &m_buffer);
6124		glDeleteBuffers(1, &m_vbo);
6125		glDeleteBuffers(1, &m_counter_buffer);
6126		glDeleteBuffers(1, &m_transform_buffer);
6127		glDeleteTextures(1, &m_buffer_tex);
6128		glDeleteProgram(m_vsp);
6129		glDeleteProgram(m_fsp);
6130		glDeleteVertexArrays(1, &m_vao);
6131		glDeleteProgramPipelines(1, &m_pipeline);
6132		return NO_ERROR;
6133	}
6134};
6135//-----------------------------------------------------------------------------
6136// 2.4.3 AdvancedSSOSubroutine
6137//-----------------------------------------------------------------------------
6138class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6139{
6140	GLuint m_texture;
6141	GLuint m_attribless_vao;
6142	GLuint m_program;
6143	GLint  m_draw_buffer;
6144
6145	virtual long Setup()
6146	{
6147		glGenTextures(1, &m_texture);
6148		glGenVertexArrays(1, &m_attribless_vao);
6149
6150		const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6151									"const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6152									"void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6153		const char* const glsl_fs =
6154			"#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6155			"writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6156			"subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6157			"  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6158			"  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6159			"  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6160			"subroutine(Brush) void Brush1(ivec2 coord) {" NL
6161			"  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6162			"  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6163			"  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6164			"  g_brush(ivec2(gl_FragCoord));" NL "}";
6165		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6166
6167		return NO_ERROR;
6168	}
6169
6170	virtual long Run()
6171	{
6172		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6173		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6174
6175		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6176		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6177		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 3, 0, GL_RGBA, GL_FLOAT,
6178					 NULL);
6179
6180		glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6181
6182		glDrawBuffer(GL_NONE);
6183		glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6184		glUseProgram(m_program);
6185		glBindVertexArray(m_attribless_vao);
6186
6187		const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6188									glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6189
6190		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6191		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6192
6193		std::vector<vec4> data(getWindowWidth() * getWindowHeight() * 3);
6194		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6195		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6196
6197		for (int layer = 0; layer < 3; ++layer)
6198		{
6199			for (int h = 0; h < getWindowHeight(); ++h)
6200			{
6201				for (int w = 0; w < getWindowWidth(); ++w)
6202				{
6203					const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
6204					if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6205					{
6206						m_context.getTestContext().getLog()
6207							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6208							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6209						return ERROR;
6210					}
6211					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6212					{
6213						m_context.getTestContext().getLog()
6214							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6215							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6216						return ERROR;
6217					}
6218					else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6219					{
6220						m_context.getTestContext().getLog()
6221							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6222							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6223						return ERROR;
6224					}
6225				}
6226			}
6227		}
6228
6229		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6230		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6231
6232		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6233		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6234
6235		for (int layer = 0; layer < 3; ++layer)
6236		{
6237			for (int h = 0; h < getWindowHeight(); ++h)
6238			{
6239				for (int w = 0; w < getWindowWidth(); ++w)
6240				{
6241					const vec4 c = data[layer * getWindowWidth() * getWindowHeight() + h * getWindowWidth() + w];
6242					if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6243					{
6244						m_context.getTestContext().getLog()
6245							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6246							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6247						return ERROR;
6248					}
6249					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6250					{
6251						m_context.getTestContext().getLog()
6252							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6253							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6254						return ERROR;
6255					}
6256					else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6257					{
6258						m_context.getTestContext().getLog()
6259							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6260							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6261						return ERROR;
6262					}
6263				}
6264			}
6265		}
6266		return NO_ERROR;
6267	}
6268
6269	virtual long Cleanup()
6270	{
6271		glDrawBuffer(m_draw_buffer);
6272		glDeleteTextures(1, &m_texture);
6273		glUseProgram(0);
6274		glDeleteProgram(m_program);
6275		glDeleteVertexArrays(1, &m_attribless_vao);
6276		return NO_ERROR;
6277	}
6278};
6279//-----------------------------------------------------------------------------
6280// 2.4.4 AdvancedSSOPerSample
6281//-----------------------------------------------------------------------------
6282class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6283{
6284	GLuint m_texture;
6285	GLuint m_pipeline;
6286	GLuint m_vao, m_vbo, m_ebo;
6287	GLuint m_vsp, m_store_fsp, m_load_fsp;
6288
6289	virtual long Setup()
6290	{
6291		m_vao		= 0;
6292		m_vbo		= 0;
6293		m_ebo		= 0;
6294		m_vsp		= 0;
6295		m_store_fsp = 0;
6296		m_load_fsp  = 0;
6297		glGenTextures(1, &m_texture);
6298		glGenProgramPipelines(1, &m_pipeline);
6299
6300		return NO_ERROR;
6301	}
6302
6303	virtual long Run()
6304	{
6305		if (!SupportedSamples(4))
6306			return NOT_SUPPORTED;
6307
6308		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6309
6310		const char* const glsl_vs =
6311			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6312			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6313		const char* const glsl_store_fs =
6314			"#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6315			"  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6316		const char* const glsl_load_fs =
6317			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6318			"layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6319			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6320			"vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6321		m_vsp		= BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6322		m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6323		m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6324
6325		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6326		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, getWindowWidth(), getWindowHeight(),
6327								GL_FALSE);
6328		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6329
6330		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6331		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6332
6333		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6334
6335		glClear(GL_COLOR_BUFFER_BIT);
6336		glBindVertexArray(m_vao);
6337		glBindProgramPipeline(m_pipeline);
6338		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6339
6340		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6341
6342		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6343		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6344
6345		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6346		{
6347			return ERROR;
6348		}
6349		return NO_ERROR;
6350	}
6351
6352	virtual long Cleanup()
6353	{
6354		glDeleteBuffers(1, &m_vbo);
6355		glDeleteBuffers(1, &m_ebo);
6356		glDeleteTextures(1, &m_texture);
6357		glDeleteProgram(m_vsp);
6358		glDeleteProgram(m_store_fsp);
6359		glDeleteProgram(m_load_fsp);
6360		glDeleteVertexArrays(1, &m_vao);
6361		glDeleteProgramPipelines(1, &m_pipeline);
6362		return NO_ERROR;
6363	}
6364};
6365
6366//-----------------------------------------------------------------------------
6367// 2.5 AdvancedCopyImage
6368//-----------------------------------------------------------------------------
6369class AdvancedCopyImage : public ShaderImageLoadStoreBase
6370{
6371	GLuint m_texture[2];
6372	GLuint m_program;
6373	GLuint m_vao, m_vbo, m_ebo;
6374
6375	virtual long Setup()
6376	{
6377		glGenTextures(2, m_texture);
6378		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6379
6380		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6381									"void main() {" NL "  gl_Position = i_position;" NL "}";
6382		const char* const glsl_fs =
6383			"#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6384			"layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6385			"  ivec2 coord = ivec2(gl_FragCoord);" NL
6386			"  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6387		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6388
6389		return NO_ERROR;
6390	}
6391
6392	virtual long Run()
6393	{
6394		glUseProgram(m_program);
6395		glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6396		glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6397
6398		std::vector<vec4> data(getWindowWidth() * getWindowHeight(), vec4(7.0f));
6399		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6400		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6401		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, &data[0]);
6402
6403		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6404		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6405		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_FLOAT, NULL);
6406
6407		glBindTexture(GL_TEXTURE_2D, 0);
6408
6409		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6410		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6411
6412		glClear(GL_COLOR_BUFFER_BIT);
6413		glBindVertexArray(m_vao);
6414		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6415
6416		std::vector<vec4> rdata(getWindowWidth() * getWindowHeight());
6417		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6418		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6419
6420		for (int h = 0; h < getWindowHeight(); ++h)
6421		{
6422			for (int w = 0; w < getWindowWidth(); ++w)
6423			{
6424				if (!IsEqual(rdata[h * getWindowWidth() + w], vec4(7.0f)))
6425				{
6426					return ERROR;
6427				}
6428			}
6429		}
6430		return NO_ERROR;
6431	}
6432
6433	virtual long Cleanup()
6434	{
6435		glUseProgram(0);
6436		glDeleteBuffers(1, &m_vbo);
6437		glDeleteBuffers(1, &m_ebo);
6438		glDeleteTextures(2, m_texture);
6439		glDeleteProgram(m_program);
6440		glDeleteVertexArrays(1, &m_vao);
6441		return NO_ERROR;
6442	}
6443};
6444//-----------------------------------------------------------------------------
6445// 2.6 AdvancedAllMips
6446//-----------------------------------------------------------------------------
6447class AdvancedAllMips : public ShaderImageLoadStoreBase
6448{
6449	GLuint m_texture;
6450	GLuint m_store_program, m_load_program;
6451	GLuint m_vao, m_vbo, m_ebo;
6452
6453	virtual long Setup()
6454	{
6455		glGenTextures(1, &m_texture);
6456		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6457
6458		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6459									"void main() {" NL "  gl_Position = i_position;" NL "}";
6460		const char* const glsl_store_fs =
6461			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6462			"  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6463			"  discard;" NL "}";
6464		const char* const glsl_load_fs =
6465			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6466			"layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6467			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6468			"    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6469			"    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6470		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6471		m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6472
6473		return NO_ERROR;
6474	}
6475
6476	virtual long Run()
6477	{
6478		glUseProgram(m_store_program);
6479		glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6480		glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6481		glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6482		glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6483		glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6484		glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6485		glUseProgram(0);
6486
6487		glUseProgram(m_load_program);
6488		glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6489		glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6490		glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6491		glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6492		glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6493		glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6494		glUseProgram(0);
6495
6496		glBindTexture(GL_TEXTURE_2D, m_texture);
6497		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6498		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6499		glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6500		glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6501		glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6502		glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6503		glBindTexture(GL_TEXTURE_2D, 0);
6504
6505		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6506		glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6507		glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6508		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6509		glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6510		glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6511
6512		glViewport(0, 0, 32, 32);
6513		glBindVertexArray(m_vao);
6514
6515		glClear(GL_COLOR_BUFFER_BIT);
6516		glUseProgram(m_store_program);
6517		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6518
6519		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6520
6521		glUseProgram(m_load_program);
6522		glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6523
6524		if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6525		{
6526			return ERROR;
6527		}
6528		return NO_ERROR;
6529	}
6530
6531	virtual long Cleanup()
6532	{
6533		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6534		glUseProgram(0);
6535		glDeleteBuffers(1, &m_vbo);
6536		glDeleteBuffers(1, &m_ebo);
6537		glDeleteTextures(1, &m_texture);
6538		glDeleteProgram(m_store_program);
6539		glDeleteProgram(m_load_program);
6540		glDeleteVertexArrays(1, &m_vao);
6541		return NO_ERROR;
6542	}
6543};
6544//-----------------------------------------------------------------------------
6545// 2.7 AdvancedCast
6546//-----------------------------------------------------------------------------
6547class AdvancedCast : public ShaderImageLoadStoreBase
6548{
6549	GLuint m_texture[2];
6550	GLuint m_program;
6551	GLuint m_vao, m_vbo, m_ebo;
6552
6553	virtual long Setup()
6554	{
6555		glGenTextures(2, m_texture);
6556		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6557
6558		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6559									"void main() {" NL "  gl_Position = i_position;" NL "}";
6560		const char* const glsl_fs =
6561			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6562			"layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6563			"void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6564			"  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6565			"  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6566			"  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6567			"  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6568		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6569
6570		return NO_ERROR;
6571	}
6572
6573	virtual long Run()
6574	{
6575		glUseProgram(m_program);
6576		glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6577		glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6578
6579		{
6580			std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6581			glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6582			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6583			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6584						 &data[0]);
6585
6586			glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6587			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6588			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6589						 &data[0]);
6590
6591			glBindTexture(GL_TEXTURE_2D, 0);
6592		}
6593
6594		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6595		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6596
6597		glClear(GL_COLOR_BUFFER_BIT);
6598		glBindVertexArray(m_vao);
6599		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6600
6601		std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6602		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6603		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6604		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6605
6606		for (int h = 0; h < getWindowHeight(); ++h)
6607		{
6608			for (int w = 0; w < getWindowWidth(); ++w)
6609			{
6610				const GLubyte c[4] = {
6611					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6612					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6613				};
6614				if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6615				{
6616					m_context.getTestContext().getLog()
6617						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6618						<< ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6619					return ERROR;
6620				}
6621			}
6622		}
6623
6624		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6625		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6626
6627		for (int h = 0; h < getWindowHeight(); ++h)
6628		{
6629			for (int w = 0; w < getWindowWidth(); ++w)
6630			{
6631				const GLubyte c[4] = {
6632					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6633					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6634				};
6635				if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6636				{
6637					m_context.getTestContext().getLog()
6638						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6639						<< ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6640					return ERROR;
6641				}
6642			}
6643		}
6644
6645		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6646		{
6647			return ERROR;
6648		}
6649		return NO_ERROR;
6650	}
6651
6652	virtual long Cleanup()
6653	{
6654		glUseProgram(0);
6655		glDeleteBuffers(1, &m_vbo);
6656		glDeleteBuffers(1, &m_ebo);
6657		glDeleteTextures(2, m_texture);
6658		glDeleteProgram(m_program);
6659		glDeleteVertexArrays(1, &m_vao);
6660		return NO_ERROR;
6661	}
6662};
6663
6664/** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6665 *
6666 *  Steps:
6667 *  - create two textures: "source" and "destination". Fill "source"
6668 *  texture with unique values. Fill "destination" texture with zeros,
6669 *  - prepare a program object that will read texel from "source" image at given
6670 *  coordinates and write its value to "destination" image at same
6671 *  coordinates,
6672 *  - bind "source" and "destination" textures as "source" and "destination"
6673 *  image uniforms,
6674 *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6675 *  corner at 1,1),
6676 *  - verify that texel values in "destination" texture match those in
6677 *  "source" texture (use glGetTexImage).
6678 *
6679 *  Test with 2D R8UI textures with following dimensions:
6680 *  - 16x16,
6681 *  - 16x17,
6682 *  - 17x16,
6683 *  - 17x17,
6684 *  - 16x18,
6685 *  - 18x16,
6686 *  - 18x18,
6687 *  - 19x16,
6688 *  - 16x19,
6689 *  - 19x19.
6690 *
6691 *  Note that default data alignment should cause problems with packing/
6692 *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6693 *  of pixel storage mode have to be changed to one byte alignment.
6694 *
6695 *  Program should consist of vertex and fragment shader. Vertex shader should
6696 *  pass vertex position through. Fragment shader should do imageLoad() and
6697 *  imageStore() operations at coordinates gl_FragCoord.
6698 **/
6699class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6700{
6701private:
6702	/* Structures */
6703	struct TextureDimensions
6704	{
6705		GLuint m_width;
6706		GLuint m_height;
6707
6708		TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6709		{
6710		}
6711	};
6712
6713	/* Typedefs */
6714	typedef std::deque<TextureDimensions> TextureDimensionsList;
6715
6716	/* Fields */
6717	GLuint				  m_destination_texture_id;
6718	GLuint				  m_program_id;
6719	TextureDimensionsList m_texture_dimensions;
6720	GLuint				  m_source_texture_id;
6721	GLuint				  m_vertex_array_object_id;
6722	GLuint				  m_vertex_buffer_id;
6723
6724public:
6725	/* Constructor */
6726	ImageLoadStoreDataAlignmentTest()
6727		: m_destination_texture_id(0)
6728		, m_program_id(0)
6729		, m_source_texture_id(0)
6730		, m_vertex_array_object_id(0)
6731		, m_vertex_buffer_id(0)
6732	{
6733		/* Nothing to be done here */
6734	}
6735
6736	/* Methods inherited from SubcaseBase */
6737	virtual long Setup()
6738	{
6739		/* Shaders code */
6740		const char* const vertex_shader_code = "#version 400 core\n"
6741											   "#extension GL_ARB_shader_image_load_store : require\n"
6742											   "\n"
6743											   "precision highp float;\n"
6744											   "\n"
6745											   "in vec4 vs_in_position;\n"
6746											   "\n"
6747											   "void main()\n"
6748											   "{\n"
6749											   "    gl_Position = vs_in_position;\n"
6750											   "}\n";
6751
6752		const char* const fragment_shader_code =
6753			"#version 400 core\n"
6754			"#extension GL_ARB_shader_image_load_store : require\n"
6755			"\n"
6756			"precision highp float;\n"
6757			"\n"
6758			"layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6759			"layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6760			"\n"
6761			"void main()\n"
6762			"{\n"
6763			"    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6764			"                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6765			"\n"
6766			"    discard;\n"
6767			"}\n";
6768
6769		/* Vertex postions for "full screen" quad, made with triangle strip */
6770		static const GLfloat m_vertex_buffer_data[] = {
6771			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6772			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6773			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6774			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6775		};
6776
6777		/* Result of BuildProgram operation */
6778		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6779
6780		/* Add all tested texture dimensions */
6781		m_texture_dimensions.push_back(TextureDimensions(16, 16));
6782		m_texture_dimensions.push_back(TextureDimensions(16, 17));
6783		m_texture_dimensions.push_back(TextureDimensions(17, 16));
6784		m_texture_dimensions.push_back(TextureDimensions(17, 17));
6785		m_texture_dimensions.push_back(TextureDimensions(16, 18));
6786		m_texture_dimensions.push_back(TextureDimensions(18, 16));
6787		m_texture_dimensions.push_back(TextureDimensions(18, 18));
6788		m_texture_dimensions.push_back(TextureDimensions(16, 19));
6789		m_texture_dimensions.push_back(TextureDimensions(19, 16));
6790		m_texture_dimensions.push_back(TextureDimensions(19, 19));
6791
6792		/* Clean previous error */
6793		glGetError();
6794
6795		/* Set single-byte data alignment */
6796		glPixelStorei(GL_PACK_ALIGNMENT, 1);
6797		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6798		GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6799
6800		/* Prepare buffer with vertex positions of "full screen" quad" */
6801		glGenBuffers(1, &m_vertex_buffer_id);
6802		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6803
6804		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6805		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6806
6807		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6808		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6809
6810		/* Generate vertex array object */
6811		glGenVertexArrays(1, &m_vertex_array_object_id);
6812		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6813
6814		/* Prepare program object */
6815		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6816									fragment_shader_code, &is_program_correct);
6817		if (false == is_program_correct)
6818		{
6819			return ERROR;
6820		}
6821
6822		/* Done */
6823		return NO_ERROR;
6824	}
6825
6826	virtual long Cleanup()
6827	{
6828		/* Reset OpenGL state */
6829		glBindBuffer(GL_ARRAY_BUFFER, 0);
6830		glBindTexture(GL_TEXTURE_2D, 0);
6831		glBindVertexArray(0);
6832		glUseProgram(0);
6833
6834		/* Delete program */
6835		if (0 != m_program_id)
6836		{
6837			glDeleteProgram(m_program_id);
6838			m_program_id = 0;
6839		}
6840
6841		/* Delete textures */
6842		if (0 != m_destination_texture_id)
6843		{
6844			glDeleteTextures(1, &m_destination_texture_id);
6845			m_destination_texture_id = 0;
6846		}
6847
6848		if (0 != m_source_texture_id)
6849		{
6850			glDeleteTextures(1, &m_source_texture_id);
6851			m_source_texture_id = 0;
6852		}
6853
6854		/* Delete vertex array object */
6855		if (0 != m_vertex_array_object_id)
6856		{
6857			glDeleteVertexArrays(1, &m_vertex_array_object_id);
6858			m_vertex_array_object_id = 0;
6859		}
6860
6861		/* Delete buffer */
6862		if (0 != m_vertex_buffer_id)
6863		{
6864			glDeleteBuffers(1, &m_vertex_buffer_id);
6865			m_vertex_buffer_id = 0;
6866		}
6867
6868		/* Done */
6869		return NO_ERROR;
6870	}
6871
6872	virtual long Run()
6873	{
6874		bool result = true;
6875
6876		/* For each dimension */
6877		for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6878			 ++it)
6879		{
6880			/* Prepare "source" and "destination" textures */
6881			GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6882								"Create2DR8UIDestinationTexture");
6883			GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6884								"Create2DR8UISourceTexture");
6885
6886			/* Copy texture data with imageLoad() and imageStore() operations */
6887			Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6888
6889			/* Compare "source" and "destination" textures */
6890			if (false ==
6891				Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6892			{
6893				m_context.getTestContext().getLog()
6894					<< tcu::TestLog::Message
6895					<< "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6896					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6897
6898				result = false;
6899			}
6900
6901			/* Destroy "source" and "destination" textures */
6902			glDeleteTextures(1, &m_destination_texture_id);
6903			glDeleteTextures(1, &m_source_texture_id);
6904
6905			m_destination_texture_id = 0;
6906			m_source_texture_id		 = 0;
6907		}
6908
6909		if (false == result)
6910		{
6911			return ERROR;
6912		}
6913
6914		/* Done */
6915		return NO_ERROR;
6916	}
6917
6918private:
6919	/* Private methods */
6920
6921	/** Binds a texture to user-specified image unit and updates relevant sampler uniform
6922	 *
6923	 * @param program_id   Program object id
6924	 * @param texture_id   Texture id
6925	 * @param image_unit   Index of image unit
6926	 * @param uniform_name Name of image uniform
6927	 **/
6928	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
6929	{
6930		/* Uniform location and invalid value */
6931		static const GLint invalid_uniform_location = -1;
6932		GLint			   image_uniform_location   = 0;
6933
6934		/* Get uniform location */
6935		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
6936		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
6937		if (invalid_uniform_location == image_uniform_location)
6938		{
6939			throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
6940		}
6941
6942		/* Bind texture to image unit */
6943		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
6944		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
6945
6946		/* Set uniform to image unit */
6947		glUniform1i(image_uniform_location, image_unit);
6948		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
6949	}
6950
6951	/** Compare two 2D R8UI textures
6952	 *
6953	 * @param left_texture_id  Id of "left" texture object
6954	 * @param right_texture_id Id of "right" texture object
6955	 * @param width            Width of the textures
6956	 * @param height           Height of the textures
6957	 *
6958	 * @return true when texture data is identical, false otherwise
6959	 **/
6960	bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
6961	{
6962		/* Size of textures */
6963		const GLuint texture_data_size = width * height;
6964
6965		/* Storage for texture data */
6966		std::vector<GLubyte> left_texture_data;
6967		std::vector<GLubyte> right_texture_data;
6968
6969		/* Alocate memory for texture data */
6970		left_texture_data.resize(texture_data_size);
6971		right_texture_data.resize(texture_data_size);
6972
6973		/* Get "left" texture data */
6974		glBindTexture(GL_TEXTURE_2D, left_texture_id);
6975		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
6976
6977		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
6978		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
6979
6980		/* Get "right" texture data */
6981		glBindTexture(GL_TEXTURE_2D, right_texture_id);
6982		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
6983
6984		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
6985		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
6986
6987		/* Compare texels */
6988		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
6989	}
6990
6991	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
6992	 *
6993	 * @param destination_texture_id Id of "destination" texture object
6994	 * @param source_texture_id      Id of "source" texture object
6995	 **/
6996	void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
6997	{
6998		/* Uniform names */
6999		static const char* const destination_image_uniform_name = "u_destination_image";
7000		static const char* const source_image_uniform_name		= "u_source_image";
7001
7002		/* Attribute name */
7003		static const char* const position_attribute_name = "vs_in_position";
7004
7005		/* Attribute location and invalid value */
7006		static const GLint invalid_attribute_location  = -1;
7007		GLint			   position_attribute_location = 0;
7008
7009		/* Set current program */
7010		glUseProgram(m_program_id);
7011		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7012
7013		/* Bind vertex array object */
7014		glBindVertexArray(m_vertex_array_object_id);
7015		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7016
7017		/* Bind buffer with quad vertex positions */
7018		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7019		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7020
7021		/* Set up position attribute */
7022		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7023		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7024		if (invalid_attribute_location == position_attribute_location)
7025		{
7026			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7027									 __LINE__);
7028		}
7029
7030		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7031							  0 /* stride */, 0);
7032		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7033
7034		glEnableVertexAttribArray(position_attribute_location);
7035		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7036
7037		/* Set up textures as source and destination images */
7038		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7039		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7040
7041		/* Execute draw */
7042		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7043		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7044	}
7045
7046	/** Create 2D R8UI texture and fills it with zeros
7047	 *
7048	 * @param width          Width of created texture
7049	 * @param height         Height of created texture
7050	 * @param out_texture_id Id of created texture, not modified if operation fails
7051	 *
7052	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7053	 **/
7054	GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7055	{
7056		/* Texture size */
7057		const GLuint texture_size = width * height;
7058
7059		/* Prepare storage for texture data */
7060		std::vector<GLubyte> texture_data;
7061		texture_data.resize(texture_size);
7062
7063		/* Set all texels */
7064		for (GLuint i = 0; i < texture_size; ++i)
7065		{
7066			texture_data[i] = 0;
7067		}
7068
7069		/* Create texture */
7070		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7071	}
7072
7073	/** Create 2D R8UI texture and fills it with increasing values, starting from 0
7074	 *
7075	 * @param width          Width of created texture
7076	 * @param height         Height of created texture
7077	 * @param out_texture_id Id of created texture, not modified if operation fails
7078	 *
7079	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7080	 **/
7081	GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7082	{
7083		/* Texture size */
7084		const GLuint texture_size = width * height;
7085
7086		/* Value of texel */
7087		GLubyte texel_value = 0;
7088
7089		/* Prepare storage for texture data */
7090		std::vector<GLubyte> texture_data;
7091		texture_data.resize(texture_size);
7092
7093		/* Set all texels */
7094		for (GLuint i = 0; i < texture_size; ++i)
7095		{
7096			texture_data[i] = texel_value++;
7097		}
7098
7099		/* Create texture */
7100		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7101	}
7102
7103	/** Create 2D R8UI texture and fills it with user-provided data
7104	 *
7105	 * @param width          Width of created texture
7106	 * @param height         Height of created texture
7107	 * @param texture_data   Texture data
7108	 * @param out_texture_id Id of created texture, not modified if operation fails
7109	 *
7110	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7111	 **/
7112	GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7113							   GLuint& out_texture_id)
7114	{
7115		GLenum err		  = 0;
7116		GLuint texture_id = 0;
7117
7118		/* Generate texture */
7119		glGenTextures(1, &texture_id);
7120		err = glGetError();
7121		if (GL_NO_ERROR != err)
7122		{
7123			return err;
7124		}
7125
7126		/* Bind texture */
7127		glBindTexture(GL_TEXTURE_2D, texture_id);
7128		err = glGetError();
7129		if (GL_NO_ERROR != err)
7130		{
7131			glDeleteTextures(1, &texture_id);
7132			return err;
7133		}
7134
7135		/* Allocate storage and fill texture */
7136		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7137					 GL_UNSIGNED_BYTE, &texture_data[0]);
7138		err = glGetError();
7139		if (GL_NO_ERROR != err)
7140		{
7141			glDeleteTextures(1, &texture_id);
7142			return err;
7143		}
7144
7145		/* Make texture complete */
7146		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7147		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7148		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7149		err = glGetError();
7150		if (GL_NO_ERROR != err)
7151		{
7152			glDeleteTextures(1, &texture_id);
7153			return err;
7154		}
7155
7156		/* Set out_texture_id */
7157		out_texture_id = texture_id;
7158
7159		/* Done */
7160		return GL_NO_ERROR;
7161	}
7162};
7163
7164/** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7165 *
7166 *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7167 *
7168 *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7169 *  | Type           | Dimensions |
7170 *  | 2D_ARRAY       | 64x64x6    |
7171 *  | 3D             | 64x64x6    |
7172 *  | CUBE_MAP       | 64         |
7173 *  | CUBE_MAP_ARRAY | 64x3       |
7174 *
7175 *  Use RGBA8 format. All layers shall be tested.
7176 *
7177 *  Program should consist of vertex and fragment shader. Vertex shader should
7178 *  pass vertex position through. Fragment shader should do imageLoad() and
7179 *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7180 *  use image2D as image type.
7181 **/
7182class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7183{
7184private:
7185	/* Structures */
7186	struct TextureShapeDefinition
7187	{
7188		GLuint m_edge;
7189		GLuint m_n_elements;
7190		GLenum m_type;
7191
7192		TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7193			: m_edge(edge), m_n_elements(n_elements), m_type(type)
7194		{
7195		}
7196	};
7197
7198	/* Typedefs */
7199	typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7200
7201	/* Fields */
7202	GLuint					   m_destination_texture_id;
7203	GLuint					   m_program_id;
7204	TextureShapeDefinitionList m_texture_shape_definitions;
7205	GLuint					   m_source_texture_id;
7206	GLuint					   m_vertex_array_object_id;
7207	GLuint					   m_vertex_buffer_id;
7208
7209public:
7210	/* Constructor */
7211	ImageLoadStoreNonLayeredBindingTest()
7212		: m_destination_texture_id(0)
7213		, m_program_id(0)
7214		, m_source_texture_id(0)
7215		, m_vertex_array_object_id(0)
7216		, m_vertex_buffer_id(0)
7217	{
7218		/* Nothing to be done here */
7219	}
7220
7221	/* Methods inherited from SubcaseBase */
7222	virtual long Setup()
7223	{
7224		/* Shaders code */
7225		const char* const vertex_shader_code = "#version 400 core\n"
7226											   "#extension GL_ARB_shader_image_load_store : require\n"
7227											   "\n"
7228											   "precision highp float;\n"
7229											   "\n"
7230											   "in vec4 vs_in_position;\n"
7231											   "\n"
7232											   "void main()\n"
7233											   "{\n"
7234											   "    gl_Position = vs_in_position;\n"
7235											   "}\n";
7236
7237		const char* const fragment_shader_code =
7238			"#version 400 core\n"
7239			"#extension GL_ARB_shader_image_load_store : require\n"
7240			"\n"
7241			"precision highp float;\n"
7242			"\n"
7243			"layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7244			"layout(rgba8) readonly  uniform image2D u_source_image;\n"
7245			"\n"
7246			"void main()\n"
7247			"{\n"
7248			"    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7249			"                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7250			"\n"
7251			"    discard;\n"
7252			"}\n";
7253
7254		/* Vertex postions for "full screen" quad, defined as a triangle strip */
7255		static const GLfloat m_vertex_buffer_data[] = {
7256			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7257			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7258			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7259			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7260		};
7261
7262		/* Result of BuildProgram operation */
7263		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7264
7265		/* Add all tested texture shapes */
7266		int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7267		m_texture_shape_definitions.push_back(
7268			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7269		m_texture_shape_definitions.push_back(
7270			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7271		m_texture_shape_definitions.push_back(
7272			TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7273		m_texture_shape_definitions.push_back(
7274			TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7275
7276		/* Prepare buffer with vertex positions of "full screen" quad" */
7277		glGenBuffers(1, &m_vertex_buffer_id);
7278		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7279
7280		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7281		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7282
7283		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7284		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7285
7286		/* Generate vertex array object */
7287		glGenVertexArrays(1, &m_vertex_array_object_id);
7288		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7289
7290		/* Prepare program object */
7291		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7292									fragment_shader_code, &is_program_correct);
7293		if (false == is_program_correct)
7294		{
7295			return ERROR;
7296		}
7297
7298		/* Done */
7299		return NO_ERROR;
7300	}
7301
7302	virtual long Cleanup()
7303	{
7304		/* Reset OpenGL state */
7305		glBindBuffer(GL_ARRAY_BUFFER, 0);
7306		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7307		glBindTexture(GL_TEXTURE_3D, 0);
7308		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7309		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7310		glBindVertexArray(0);
7311		glUseProgram(0);
7312
7313		/* Delete program */
7314		if (0 != m_program_id)
7315		{
7316			glDeleteProgram(m_program_id);
7317			m_program_id = 0;
7318		}
7319
7320		/* Delete textures */
7321		if (0 != m_destination_texture_id)
7322		{
7323			glDeleteTextures(1, &m_destination_texture_id);
7324			m_destination_texture_id = 0;
7325		}
7326
7327		if (0 != m_source_texture_id)
7328		{
7329			glDeleteTextures(1, &m_source_texture_id);
7330			m_source_texture_id = 0;
7331		}
7332
7333		/* Delete vertex array object */
7334		if (0 != m_vertex_array_object_id)
7335		{
7336			glDeleteVertexArrays(1, &m_vertex_array_object_id);
7337			m_vertex_array_object_id = 0;
7338		}
7339
7340		/* Delete buffer */
7341		if (0 != m_vertex_buffer_id)
7342		{
7343			glDeleteBuffers(1, &m_vertex_buffer_id);
7344			m_vertex_buffer_id = 0;
7345		}
7346
7347		/* Done */
7348		return NO_ERROR;
7349	}
7350
7351	virtual long Run()
7352	{
7353		bool result = true;
7354
7355		/* For each shape */
7356		for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7357			 m_texture_shape_definitions.end() != it; ++it)
7358		{
7359			const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7360
7361			/* Prepare "source" and "destination" textures */
7362			GLU_EXPECT_NO_ERROR(
7363				CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7364				"Create2DR8UIDestinationTexture");
7365			GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7366								"Create2DR8UISourceTexture");
7367
7368			/* Copy texture data with imageLoad() and imageStore() operations */
7369			CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7370
7371			/* Compare "source" and "destination" textures */
7372			if (false ==
7373				CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7374			{
7375				const char* texture_type = "";
7376				switch (it->m_type)
7377				{
7378				case GL_TEXTURE_2D_ARRAY:
7379					texture_type = "2d array";
7380					break;
7381				case GL_TEXTURE_3D:
7382					texture_type = "3d";
7383					break;
7384				case GL_TEXTURE_CUBE_MAP:
7385					texture_type = "Cube map";
7386					break;
7387				case GL_TEXTURE_CUBE_MAP_ARRAY:
7388					texture_type = "Cube map array";
7389					break;
7390				}
7391
7392				m_context.getTestContext().getLog()
7393					<< tcu::TestLog::Message
7394					<< "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7395					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7396
7397				result = false;
7398			}
7399
7400			/* Destroy "source" and "destination" textures */
7401			glDeleteTextures(1, &m_destination_texture_id);
7402			glDeleteTextures(1, &m_source_texture_id);
7403
7404			m_destination_texture_id = 0;
7405			m_source_texture_id		 = 0;
7406		}
7407
7408		if (false == result)
7409		{
7410			return ERROR;
7411		}
7412
7413		/* Done */
7414		return NO_ERROR;
7415	}
7416
7417private:
7418	/* Private methods */
7419
7420	/** Binds a texture to user-specified image unit and update relevant sampler uniform
7421	 *
7422	 * @param program_id   Program object id
7423	 * @param texture_id   Texture id
7424	 * @param image_unit   Index of image unit
7425	 * @param layer        Index of layer bound to unit
7426	 * @param uniform_name Name of image uniform
7427	 **/
7428	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7429							const char* uniform_name)
7430	{
7431		static const GLint invalid_uniform_location = -1;
7432		GLint			   image_uniform_location   = 0;
7433
7434		/* Get uniform location */
7435		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7436		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7437		if (invalid_uniform_location == image_uniform_location)
7438		{
7439			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7440		}
7441
7442		/* Bind texture to image unit */
7443		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7444						   GL_RGBA8);
7445		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7446
7447		/* Set uniform to image unit */
7448		glUniform1i(image_uniform_location, image_unit);
7449		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7450	}
7451
7452	/** Compare two 2D R8UI textures
7453	 *
7454	 * @param left_texture_id  Id of "left" texture object
7455	 * @param right_texture_id Id of "right" texture object
7456	 * @param edge             Length of texture edge
7457	 * @param n_layers         Number of layers to compare
7458	 * @param type             Type of texture
7459	 *
7460	 * @return true when texture data is found identical, false otherwise
7461	 **/
7462	bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7463							  GLenum type)
7464	{
7465		static const GLuint n_components	  = 4; /* RGBA */
7466		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7467
7468		/* Storage for texture data */
7469		std::vector<GLubyte> left_texture_data;
7470		std::vector<GLubyte> right_texture_data;
7471
7472		ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7473		ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7474
7475		/* Compare texels */
7476		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7477	}
7478
7479	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7480	 *
7481	 * @param destination_texture_id Id of "destination" texture object
7482	 * @param source_texture_id      Id of "source" texture object
7483	 * @param n_layers               Number of layers
7484	 **/
7485	void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7486	{
7487		for (GLuint layer = 0; layer < n_layers; ++layer)
7488		{
7489			CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7490		}
7491	}
7492
7493	/** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7494	 *
7495	 * @param destination_texture_id Id of "destination" texture object
7496	 * @param source_texture_id      Id of "source" texture object
7497	 * @param layer                  Index of layer
7498	 **/
7499	void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7500	{
7501		/* Uniform names */
7502		static const char* const destination_image_uniform_name = "u_destination_image";
7503		static const char* const source_image_uniform_name		= "u_source_image";
7504
7505		/* Attribute name */
7506		static const char* const position_attribute_name = "vs_in_position";
7507
7508		/* Attribute location and invalid value */
7509		static const GLint invalid_attribute_location  = -1;
7510		GLint			   position_attribute_location = 0;
7511
7512		/* Set current program */
7513		glUseProgram(m_program_id);
7514		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7515
7516		/* Bind vertex array object */
7517		glBindVertexArray(m_vertex_array_object_id);
7518		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7519
7520		/* Bind buffer with quad vertex positions */
7521		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7522		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7523
7524		/* Set up vertex attribute array for position attribute */
7525		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7526		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7527		if (invalid_attribute_location == position_attribute_location)
7528		{
7529			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7530									 __LINE__);
7531		}
7532
7533		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7534							  0 /* stride */, 0 /* pointer */);
7535		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7536
7537		glEnableVertexAttribArray(position_attribute_location);
7538		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7539
7540		/* Set up textures as source and destination image samplers */
7541		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7542						   destination_image_uniform_name);
7543		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7544
7545		/* Execute draw */
7546		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7547		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7548	}
7549
7550	/** Creates RGBA8 texture of given type and fills it with zeros
7551	 *
7552	 * @param edge           Edge of created texture
7553	 * @param n_elements     Number of elements in texture array
7554	 * @param target         Target of created texture
7555	 * @param out_texture_id Id of created texture, not modified if operation fails
7556	 *
7557	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7558	 **/
7559	GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7560	{
7561		/* Constasts to calculate texture size */
7562		static const GLuint n_components = 4; /* RGBA */
7563		const GLuint		layer_size   = edge * edge * n_components;
7564		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7565		const GLuint		texture_size = layer_size * n_layers;
7566
7567		/* Prepare storage for texture data */
7568		std::vector<GLubyte> texture_data;
7569		texture_data.resize(texture_size);
7570
7571		/* Set all texels */
7572		for (GLuint i = 0; i < texture_size; ++i)
7573		{
7574			texture_data[i] = 0;
7575		}
7576
7577		/* Create texture */
7578		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7579	}
7580
7581	/** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7582	 *
7583	 * @param edge           Edge of created texture
7584	 * @param n_elements     Number of elements in texture array
7585	 * @param target         Target of created texture
7586	 * @param out_texture_id Id of created texture, not modified if operation fails
7587	 *
7588	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7589	 **/
7590	GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7591	{
7592		/* Constants to calculate texture size */
7593		static const GLuint n_components = 4; /* RGBA */
7594		const GLuint		layer_size   = edge * edge * n_components;
7595		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7596		const GLuint		texture_size = layer_size * n_layers;
7597
7598		/* Value of texel */
7599		GLubyte texel[4] = { 0, 0, 0, 0xaa };
7600
7601		/* Prepare storage for texture data */
7602		std::vector<GLubyte> texture_data;
7603		texture_data.resize(texture_size);
7604
7605		/* Set all texels */
7606		for (GLuint layer = 0; layer < n_layers; ++layer)
7607		{
7608			const GLuint layer_offset = layer_size * layer;
7609
7610			texel[2] = static_cast<GLubyte>(layer);
7611
7612			for (GLuint y = 0; y < edge; ++y)
7613			{
7614				const GLuint line_offset = y * edge * n_components + layer_offset;
7615
7616				texel[1] = static_cast<GLubyte>(y);
7617
7618				for (GLuint x = 0; x < edge; ++x)
7619				{
7620					const GLuint texel_offset = x * n_components + line_offset;
7621					texel[0]				  = static_cast<GLubyte>(x);
7622
7623					for (GLuint component = 0; component < n_components; ++component)
7624					{
7625						texture_data[texel_offset + component] = texel[component];
7626					}
7627				}
7628			}
7629		}
7630
7631		/* Create texture */
7632		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7633	}
7634
7635	/** Creates RGBA8 texture of given type and fills it provided data
7636	 *
7637	 * @param edge           Edge of created texture
7638	 * @param n_elements     Number of elements in texture array
7639	 * @param target         Target of created texture
7640	 * @param texture_data   Texture data
7641	 * @param out_texture_id Id of created texture, not modified if operation fails
7642	 *
7643	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7644	 **/
7645	GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7646							  GLuint& out_texture_id)
7647	{
7648		GLenum err		  = 0;
7649		GLuint texture_id = 0;
7650
7651		/* Generate texture */
7652		glGenTextures(1, &texture_id);
7653		err = glGetError();
7654		if (GL_NO_ERROR != err)
7655		{
7656			return err;
7657		}
7658
7659		/* Bind texture */
7660		glBindTexture(target, texture_id);
7661		err = glGetError();
7662		if (GL_NO_ERROR != err)
7663		{
7664			glDeleteTextures(1, &texture_id);
7665			return err;
7666		}
7667
7668		/* Allocate storage and fill texture */
7669		if (GL_TEXTURE_CUBE_MAP != target)
7670		{
7671			glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7672						 GL_UNSIGNED_BYTE, &texture_data[0]);
7673		}
7674		else
7675		{
7676			const GLuint n_components = 4;
7677			const GLuint layer_size   = edge * edge * n_components;
7678
7679			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7680						 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7681			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7682						 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7683			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7684						 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7685			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7686						 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7687			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7688						 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7689			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7690						 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7691		}
7692		err = glGetError();
7693		if (GL_NO_ERROR != err)
7694		{
7695			glDeleteTextures(1, &texture_id);
7696			return err;
7697		}
7698
7699		/* Make texture complete */
7700		glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7701		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7702		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7703		err = glGetError();
7704		if (GL_NO_ERROR != err)
7705		{
7706			glDeleteTextures(1, &texture_id);
7707			return err;
7708		}
7709
7710		/* Set out_texture_id */
7711		out_texture_id = texture_id;
7712
7713		/* Done */
7714		return GL_NO_ERROR;
7715	}
7716
7717	/** Extracts texture data
7718	 *
7719	 * @param texture_id   Id of texture object
7720	 * @param edge         Length of texture edge
7721	 * @param n_layers     Number of layers
7722	 * @param target       Target of texture
7723	 * @param texture_data Extracted texture data
7724	 **/
7725	void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7726							std::vector<GLubyte>& texture_data)
7727	{
7728		static const GLuint n_components	  = 4; /* RGBA */
7729		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7730
7731		/* Alocate memory for texture data */
7732		texture_data.resize(texture_data_size);
7733
7734		/* Bind texture */
7735		glBindTexture(target, texture_id);
7736		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7737
7738		/* Get data */
7739		if (GL_TEXTURE_CUBE_MAP != target)
7740		{
7741			glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7742		}
7743		else
7744		{
7745			const GLuint layer_size = edge * edge * n_components;
7746
7747			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7748			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7749			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7750			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7751			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7752			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7753		}
7754
7755		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7756	}
7757
7758	/** Get number of layers per single element for given type of texture
7759	 *
7760	 * @param target Target of texture
7761	 *
7762	 * @return Number of layers
7763	 **/
7764	GLuint GetLayersPerElement(GLenum target)
7765	{
7766		switch (target)
7767		{
7768		case GL_TEXTURE_2D_ARRAY:
7769		case GL_TEXTURE_3D:
7770			return 1;
7771			break;
7772		case GL_TEXTURE_CUBE_MAP:
7773		case GL_TEXTURE_CUBE_MAP_ARRAY:
7774			return 6;
7775			break;
7776		default:
7777			throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7778			break;
7779		}
7780	}
7781
7782	/** Get total number of layers in texture of given type and number of array elements
7783	 *
7784	 * @param n_elements Number of elements in texture array
7785	 * @param target     Target of texture
7786	 *
7787	 * @return Number of layers
7788	 **/
7789	GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7790	{
7791		return GetLayersPerElement(target) * n_elements;
7792	}
7793};
7794
7795/** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7796 *
7797 *  Load from incomplete textures should return 0.
7798 *  Store to incomplete textures should be ignored.
7799 *
7800 *  Steps:
7801 *  - create two incomplete textures: "incomplete_source" and
7802 *  "incomplete_destination",
7803 *  - create two complete textures: "complete_source" and
7804 *  "complete_destination",
7805 *  - fill all textures with unique values,
7806 *  - prepare program that will:
7807 *      * load texel from "incomplete_source" and store its value to
7808 *      "complete_destination",
7809 *      * load texel from "complete_source" and store its value to
7810 *      "incomplete_destination".
7811 *  - bind textures to corresponding image uniforms
7812 *  - execute program for all texels,
7813 *  - verify that "incomplete_destination" was not modified and
7814 *  "complete_destination" is filled with zeros.
7815 *
7816 *  Texture is considered incomplete when it has enabled mipmaping (see below)
7817 *  and does not have all mipmap levels defined.  But for the case of Image
7818 *  accessing, it is considered invalid if it is mipmap-incomplete and the
7819 *  level is different to the base level (base-incomplete).
7820 *
7821 *  Creation of incomplete texture:
7822 *  - generate and bind texture object id,
7823 *  - call TexImage2D with <level>: 0,
7824 *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7825 *  sure, it should be initial value),
7826 *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7827 *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7828 *  height)).
7829 *
7830 *  Creation of complete texture:
7831 *  - generate and bind texture object id,
7832 *  - call TexImage2D with <level>: 0,
7833 *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7834 *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7835 *
7836 *  Binding:
7837 *  - Set level == base_level for complete destinations.
7838 *  - Set level != base_level for incomplete destinations that are using
7839 *    mipmap-incomplete textures.
7840 *
7841 *  Test with 2D 64x64 RGBA8 textures.
7842 *
7843 *  Program should consist of vertex and fragment shader. Vertex shader should
7844 *  pass vertex position through. Fragment shader should do imageLoad() and
7845 *  imageStore() operations at coordinates gl_FragCoord.
7846 **/
7847class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7848{
7849private:
7850	/* Constants */
7851	/* Magic numbers that will identify textures, which will be used as their
7852	 * texel value.
7853	 */
7854	static const GLubyte m_complete_destination_magic_number   = 0x11;
7855	static const GLubyte m_complete_source_magic_number		   = 0x22;
7856	static const GLubyte m_incomplete_destination_magic_number = 0x33;
7857	static const GLubyte m_incomplete_source_magic_number	  = 0x44;
7858
7859	/* Texture edge */
7860	GLuint m_texture_edge;
7861
7862	/* Fields */
7863	GLuint m_complete_destination_texture_id;
7864	GLuint m_complete_source_texture_id;
7865	GLuint m_incomplete_destination_texture_id;
7866	GLuint m_incomplete_source_texture_id;
7867	GLuint m_program_id;
7868	GLuint m_vertex_array_object_id;
7869	GLuint m_vertex_buffer_id;
7870
7871public:
7872	/* Constructor */
7873	ImageLoadStoreIncompleteTexturesTest()
7874		: m_texture_edge(0)
7875		, m_complete_destination_texture_id(0)
7876		, m_complete_source_texture_id(0)
7877		, m_incomplete_destination_texture_id(0)
7878		, m_incomplete_source_texture_id(0)
7879		, m_program_id(0)
7880		, m_vertex_array_object_id(0)
7881		, m_vertex_buffer_id(0)
7882	{
7883		/* Nothing to be done here */
7884	}
7885
7886	/* Methods inherited from SubcaseBase */
7887	virtual long Setup()
7888	{
7889		/* Shaders code */
7890		const char* const vertex_shader_code = "#version 400 core\n"
7891											   "#extension GL_ARB_shader_image_load_store : require\n"
7892											   "\n"
7893											   "precision highp float;\n"
7894											   "\n"
7895											   "in vec4 vs_in_position;\n"
7896											   "\n"
7897											   "void main()\n"
7898											   "{\n"
7899											   "    gl_Position = vs_in_position;\n"
7900											   "}\n";
7901
7902		const char* const fragment_shader_code =
7903			"#version 400 core\n"
7904			"#extension GL_ARB_shader_image_load_store : require\n"
7905			"\n"
7906			"precision highp float;\n"
7907			"\n"
7908			"layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7909			"layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
7910			"layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7911			"layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
7912			"\n"
7913			"void main()\n"
7914			"{\n"
7915			"    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
7916			"    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7917
7918			"    imageStore(u_complete_destination_image,\n"
7919			"               ivec2(gl_FragCoord),\n"
7920			"               incomplete_loaded_color);\n"
7921			"    imageStore(u_incomplete_destination_image,\n"
7922			"               ivec2(gl_FragCoord),\n"
7923			"               complete_loaded_color);\n"
7924			"\n"
7925			"    discard;\n"
7926			"}\n";
7927
7928		/* Vertex postions for "full screen" quad, made with triangle strip */
7929		static const GLfloat m_vertex_buffer_data[] = {
7930			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7931			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7932			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7933			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7934		};
7935
7936		/* Result of BuildProgram operation */
7937		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7938
7939		/* Clean previous error */
7940		glGetError();
7941
7942		m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7943
7944		/* Prepare textures */
7945		GLU_EXPECT_NO_ERROR(
7946			Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
7947			"Create2DRGBA8CompleteTexture");
7948		GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
7949							"Create2DRGBA8CompleteTexture");
7950		GLU_EXPECT_NO_ERROR(
7951			Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
7952			"Create2DRGBA8IncompleteTexture");
7953		GLU_EXPECT_NO_ERROR(
7954			Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
7955			"Create2DRGBA8IncompleteTexture");
7956
7957		/* Prepare buffer with vertex positions of "full screen" quad" */
7958		glGenBuffers(1, &m_vertex_buffer_id);
7959		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7960
7961		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7962		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7963
7964		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7965		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7966
7967		/* Generate vertex array object */
7968		glGenVertexArrays(1, &m_vertex_array_object_id);
7969		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7970
7971		/* Prepare program object */
7972		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
7973									fragment_shader_code, &is_program_correct);
7974
7975		if (false == is_program_correct)
7976		{
7977			return ERROR;
7978		}
7979
7980		/* Done */
7981		return NO_ERROR;
7982	}
7983
7984	virtual long Cleanup()
7985	{
7986		/* Reset OpenGL state */
7987		glBindBuffer(GL_ARRAY_BUFFER, 0);
7988		glBindTexture(GL_TEXTURE_2D, 0);
7989		glBindVertexArray(0);
7990		glUseProgram(0);
7991
7992		/* Delete program */
7993		if (0 != m_program_id)
7994		{
7995			glDeleteProgram(m_program_id);
7996			m_program_id = 0;
7997		}
7998
7999		/* Delete textures */
8000		if (0 != m_complete_destination_texture_id)
8001		{
8002			glDeleteTextures(1, &m_complete_destination_texture_id);
8003			m_complete_destination_texture_id = 0;
8004		}
8005
8006		if (0 != m_complete_source_texture_id)
8007		{
8008			glDeleteTextures(1, &m_complete_source_texture_id);
8009			m_complete_source_texture_id = 0;
8010		}
8011
8012		if (0 != m_incomplete_destination_texture_id)
8013		{
8014			glDeleteTextures(1, &m_incomplete_destination_texture_id);
8015			m_incomplete_destination_texture_id = 0;
8016		}
8017
8018		if (0 != m_incomplete_source_texture_id)
8019		{
8020			glDeleteTextures(1, &m_incomplete_source_texture_id);
8021			m_incomplete_source_texture_id = 0;
8022		}
8023
8024		/* Delete vertex array object */
8025		if (0 != m_vertex_array_object_id)
8026		{
8027			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8028			m_vertex_array_object_id = 0;
8029		}
8030
8031		/* Delete buffer */
8032		if (0 != m_vertex_buffer_id)
8033		{
8034			glDeleteBuffers(1, &m_vertex_buffer_id);
8035			m_vertex_buffer_id = 0;
8036		}
8037
8038		/* Done */
8039		return NO_ERROR;
8040	}
8041
8042	virtual long Run()
8043	{
8044		bool result = true;
8045
8046		/* Copy textures data with imageLoad() and imageStore() operations */
8047		Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8048							m_complete_source_texture_id, m_incomplete_source_texture_id);
8049
8050		glMemoryBarrier(GL_ALL_BARRIER_BITS);
8051
8052		/* Verify that store to "incomplete destination" was ignored */
8053		if (true ==
8054			CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8055		{
8056			m_context.getTestContext().getLog()
8057				<< tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8058				<< tcu::TestLog::EndMessage;
8059
8060			result = false;
8061		}
8062
8063		/* Verify that load from "incomplete source" returned 0 */
8064		if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8065		{
8066			m_context.getTestContext().getLog()
8067				<< tcu::TestLog::Message
8068				<< "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8069				<< tcu::TestLog::EndMessage;
8070
8071			result = false;
8072		}
8073
8074		if (false == result)
8075		{
8076			return ERROR;
8077		}
8078
8079		/* Done */
8080		return NO_ERROR;
8081	}
8082
8083private:
8084	/* Private methods */
8085
8086	/** Bind texture to image unit and sets image uniform to that unit
8087	 *
8088	 * @param program_id   Program object id
8089	 * @param texture_id   Texture id
8090	 * @param level        Texture level
8091	 * @param image_unit   Index of image unit
8092	 * @param uniform_name Name of image uniform
8093	 **/
8094	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8095	{
8096		/* Uniform location and invalid value */
8097		static const GLint invalid_uniform_location = -1;
8098		GLint			   image_uniform_location   = 0;
8099
8100		/* Get uniform location */
8101		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8102		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8103		if (invalid_uniform_location == image_uniform_location)
8104		{
8105			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8106		}
8107
8108		/* Bind texture to image unit */
8109		glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8110		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8111
8112		/* Set uniform to image unit */
8113		glUniform1i(image_uniform_location, image_unit);
8114		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8115	}
8116
8117	/** Check if texture is filled with black color, zeros
8118	 *
8119	 * @param texture_id Id of texture object
8120	 *
8121	 * @return true when texture is fully black, false otherwise
8122	 **/
8123	bool CheckIfTextureIsBlack(GLuint texture_id)
8124	{
8125		/* Constants to calculate size of texture */
8126		static const GLuint n_components	  = 4; /* RGBA */
8127		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8128
8129		/* Storage for texture data */
8130		std::vector<GLubyte> black_texture_data;
8131		std::vector<GLubyte> texture_data;
8132
8133		/* Allocate memory */
8134		black_texture_data.resize(texture_data_size);
8135		texture_data.resize(texture_data_size);
8136
8137		/* Set all texels to black */
8138		for (GLuint i = 0; i < texture_data_size; ++i)
8139		{
8140			black_texture_data[i] = 0;
8141		}
8142
8143		/* Bind texture */
8144		glBindTexture(GL_TEXTURE_2D, texture_id);
8145		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8146
8147		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8148		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8149
8150		/* Compare texels */
8151		return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8152	}
8153
8154	/** Check if texture was modified
8155	 *
8156	 * @param texture_id   Id of texture object
8157	 * @param nagic_number Magic number that was to create texture
8158	 *
8159	 * @return true if texture contents match expected values, false otherwise
8160	 **/
8161	bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8162	{
8163		/* Constants to calculate size of texture */
8164		static const GLuint n_components	  = 4; /* RGBA */
8165		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8166
8167		/* Storage for texture data */
8168		std::vector<GLubyte> expected_texture_data;
8169		std::vector<GLubyte> texture_data;
8170
8171		/* Allocate memory */
8172		expected_texture_data.resize(texture_data_size);
8173		texture_data.resize(texture_data_size);
8174
8175		/* Prepare expected texels */
8176		for (GLuint y = 0; y < m_texture_edge; ++y)
8177		{
8178			const GLuint line_offset = y * m_texture_edge * n_components;
8179
8180			for (GLuint x = 0; x < m_texture_edge; ++x)
8181			{
8182				const GLuint texel_offset = x * n_components + line_offset;
8183
8184				SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8185						 magic_number);
8186			}
8187		}
8188
8189		/* Bind texture */
8190		glBindTexture(GL_TEXTURE_2D, texture_id);
8191		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8192
8193		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8194		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8195
8196		/* Compare texels, true when textures are different */
8197		return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8198	}
8199
8200	/** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8201	 *
8202	 * @param complete_destination_texture_id   Id of "complete destination" texture object
8203	 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8204	 * @param complete_source_texture_id        Id of "complete source" texture object
8205	 * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8206	 **/
8207	void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8208							 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8209	{
8210		/* Uniform names */
8211		static const char* const complete_destination_image_uniform_name   = "u_complete_destination_image";
8212		static const char* const complete_source_image_uniform_name		   = "u_complete_source_image";
8213		static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8214		static const char* const incomplete_source_image_uniform_name	  = "u_incomplete_source_image";
8215
8216		/* Attribute name */
8217		static const char* const position_attribute_name = "vs_in_position";
8218
8219		/* Attribute location and invalid value */
8220		static const GLint invalid_attribute_location  = -1;
8221		GLint			   position_attribute_location = 0;
8222
8223		/* Set current program */
8224		glUseProgram(m_program_id);
8225		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8226
8227		/* Bind vertex array object */
8228		glBindVertexArray(m_vertex_array_object_id);
8229		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8230
8231		/* Bind buffer with quad vertex positions */
8232		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8233		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8234
8235		/* Setup position attribute */
8236		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8237		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8238		if (invalid_attribute_location == position_attribute_location)
8239		{
8240			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8241									 __LINE__);
8242		}
8243
8244		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8245		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8246
8247		glEnableVertexAttribArray(position_attribute_location);
8248		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8249
8250		/* Setup textures as source and destination images */
8251		BindTextureToImage(m_program_id, complete_destination_texture_id,
8252						   0 /* texture level */, 0 /* image_unit */,
8253						   complete_destination_image_uniform_name);
8254		BindTextureToImage(m_program_id, complete_source_texture_id,
8255						   0 /* texture level */, 1 /* image_unit */,
8256						   complete_source_image_uniform_name);
8257		BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8258						   2 /* texture level */, 2 /* image_unit */,
8259						   incomplete_destination_image_uniform_name);
8260		BindTextureToImage(m_program_id, incomplete_source_texture_id,
8261						   2 /* texture level */, 3 /* image_unit */,
8262						   incomplete_source_image_uniform_name);
8263
8264		/* Execute draw */
8265		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8266		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8267	}
8268
8269	/** Create complete 2D RGBA8 texture.
8270	 *
8271	 * @param magic_number   Magic number of texture
8272	 * @param out_texture_id Id of created texture, not modified if operation fails
8273	 *
8274	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8275	 **/
8276	GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8277	{
8278		/* Constants to calculate size of texture */
8279		static const GLuint n_components	  = 4; /* RGBA */
8280		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8281
8282		/* Error code */
8283		GLenum err = 0;
8284
8285		/* Texture id */
8286		GLuint texture_id = 0;
8287
8288		/* Prepare storage for texture data */
8289		std::vector<GLubyte> texture_data;
8290		texture_data.resize(texture_data_size);
8291
8292		/* Prepare texture data */
8293		for (GLuint y = 0; y < m_texture_edge; ++y)
8294		{
8295			const GLuint line_offset = y * m_texture_edge * n_components;
8296
8297			for (GLuint x = 0; x < m_texture_edge; ++x)
8298			{
8299				const GLuint texel_offset = x * n_components + line_offset;
8300
8301				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8302			}
8303		}
8304
8305		/* Generate texture */
8306		glGenTextures(1, &texture_id);
8307		err = glGetError();
8308		if (GL_NO_ERROR != err)
8309		{
8310			return err;
8311		}
8312
8313		/* Bind texture */
8314		glBindTexture(GL_TEXTURE_2D, texture_id);
8315		err = glGetError();
8316		if (GL_NO_ERROR != err)
8317		{
8318			glDeleteTextures(1, &texture_id);
8319			return err;
8320		}
8321
8322		/* Allocate storage and fill texture */
8323		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8324					 GL_UNSIGNED_BYTE, &texture_data[0]);
8325		err = glGetError();
8326		if (GL_NO_ERROR != err)
8327		{
8328			glDeleteTextures(1, &texture_id);
8329			return err;
8330		}
8331
8332		/* Make texture complete */
8333		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8334		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8335		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8336		err = glGetError();
8337		if (GL_NO_ERROR != err)
8338		{
8339			glDeleteTextures(1, &texture_id);
8340			return err;
8341		}
8342
8343		/* Set out_texture_id */
8344		out_texture_id = texture_id;
8345
8346		/* Done */
8347		return GL_NO_ERROR;
8348	}
8349
8350	/** Create incomplete 2D RGBA8 texture
8351	 *
8352	 * @param magic_number   Magic number of texture
8353	 * @param out_texture_id Id of created texture, not modified if operation fails
8354	 *
8355	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8356	 **/
8357	GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8358	{
8359		/* Constants to calculate size of texture */
8360		static const GLuint n_components	  = 4; /* RGBA */
8361		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8362
8363		/* Error code */
8364		GLenum err = 0;
8365
8366		/* Texture id */
8367		GLuint texture_id = 0;
8368
8369		/* Prepare storage for texture data */
8370		std::vector<GLubyte> texture_data;
8371		texture_data.resize(texture_data_size);
8372
8373		/* Prepare texture data */
8374		for (GLuint y = 0; y < m_texture_edge; ++y)
8375		{
8376			const GLuint line_offset = y * m_texture_edge * n_components;
8377
8378			for (GLuint x = 0; x < m_texture_edge; ++x)
8379			{
8380				const GLuint texel_offset = x * n_components + line_offset;
8381
8382				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8383			}
8384		}
8385
8386		/* Generate texture */
8387		glGenTextures(1, &texture_id);
8388		err = glGetError();
8389		if (GL_NO_ERROR != err)
8390		{
8391			return err;
8392		}
8393
8394		/* Bind texture */
8395		glBindTexture(GL_TEXTURE_2D, texture_id);
8396		err = glGetError();
8397		if (GL_NO_ERROR != err)
8398		{
8399			glDeleteTextures(1, &texture_id);
8400			return err;
8401		}
8402
8403		/* Allocate storage and fill texture */
8404		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8405					 GL_UNSIGNED_BYTE, &texture_data[0]);
8406		err = glGetError();
8407		if (GL_NO_ERROR != err)
8408		{
8409			glDeleteTextures(1, &texture_id);
8410			return err;
8411		}
8412
8413		/* Make texture incomplete */
8414		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8415		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8416		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8417		err = glGetError();
8418		if (GL_NO_ERROR != err)
8419		{
8420			glDeleteTextures(1, &texture_id);
8421			return err;
8422		}
8423
8424		/* Set out_texture_id */
8425		out_texture_id = texture_id;
8426
8427		/* Done */
8428		return GL_NO_ERROR;
8429	}
8430
8431	/** Prepare "unique" texels.
8432	 *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8433	 *
8434	 * @param texel        Storage of texel
8435	 * @param x_coordinate X coordiante of texel
8436	 * @param y_coordinate Y coordinate of texel
8437	 * @param magic_number Magic number of texture
8438	 **/
8439	void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8440	{
8441		texel[0] = x_coordinate;
8442		texel[1] = y_coordinate;
8443		texel[2] = magic_number;
8444		texel[3] = 0xcc;
8445	}
8446};
8447
8448/** Test "Refer to the same image unit using multiple uniforms", description follows.
8449 *
8450 * Steps:
8451 * - prepare program object, see details below,
8452 * - prepare 2D R32I texture, width should be equal to the number of image
8453 * uniforms used by program object, height should be 2, fill first row with
8454 * unique values, fill second row with zeros,
8455 * - bind texture to first image unit,
8456 * - set all image uniforms to first image unit,
8457 * - execute program for a single vertex,
8458 * - verify that:
8459 *     - values in first row were negated,
8460 *     - values from first row were copied to second row,
8461 *
8462 * Repeat steps to test all shader stages that support at least 2 image
8463 * uniforms.
8464 *
8465 * Program has to contain all necessary shader stages. Use boilerplate shaders
8466 * for shader stages that are not important for the test.
8467 *
8468 * Tested shader stage should:
8469 * - Use as many different image formats as possible, image formats compatible
8470 * with R32I:
8471 *     * rg16f
8472 *     * r11f_g11f_b10f
8473 *     * r32f
8474 *     * rgb10_a2ui
8475 *     * rgba8ui
8476 *     * rg16ui
8477 *     * r32ui
8478 *     * rgba8i
8479 *     * rg16i
8480 *     * r32i
8481 *     * rgb10_a2
8482 *     * rgba8
8483 *     * rg16
8484 *     * rgba8_snorm
8485 *     * rg16_snorm.
8486 * - Declare maximum allowed number of image uniforms,
8487 *
8488 *     layout(format) uniform gimage2D u_image;
8489 *
8490 * where <format> is selected image format, <gimage2D> is type of 2D image
8491 * compatible with <format> and <u_image> is unique name of uniform.
8492 * Note that image uniforms cannot be declared as array, due to different image
8493 * formats. Therefore separate uniforms have to be used.
8494 * - Include following code snippet:
8495 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8496 * {
8497 *     vec row_1_coord(i,0);
8498 *     vec row_2_coord(i,1);
8499 *
8500 *     row_1_value = imageLoad(u_image[i], row_1_coord);
8501 *     imageStore(u_image[i], row_1_coord, -row_1_value);
8502 *     imageStore(u_image[i], row_2_coord, row_1_value);
8503 * }
8504 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8505 * stage.
8506 **/
8507class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8508{
8509private:
8510	/* Types */
8511	/** Details of image format
8512	 *
8513	 **/
8514	struct imageFormatDetails
8515	{
8516		typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8517
8518		const char*			m_image_format;
8519		const char*			m_image_type;
8520		const char*			m_color_type;
8521		GLenum				m_image_unit_format;
8522		verificationRoutine m_verification_routine;
8523	};
8524
8525	template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8526	struct Masks
8527	{
8528		/** Get mask of bits used to store in bit-field
8529		 *
8530		 * @return Mask
8531		 **/
8532		static inline T RawMask()
8533		{
8534			static const T mask = ValueMask() << OFFSET;
8535
8536			return mask;
8537		}
8538
8539		/** Get mask of bits used to store value.
8540		 *
8541		 * @return Mask
8542		 **/
8543		static inline T ValueMask()
8544		{
8545			static const T mask = (1 << SIZE) - 1;
8546
8547			return mask;
8548		}
8549
8550		/** Get offset.
8551		 *
8552		 * @return offset
8553		 **/
8554		static inline T Offset()
8555		{
8556			return OFFSET;
8557		}
8558	};
8559
8560	template <typename T, GLuint SIZE, GLuint OFFSET>
8561	struct Masks<T, SIZE, OFFSET, false>
8562	{
8563		/** Get mask of bits used to store in bit-field
8564		 *
8565		 * @return Mask
8566		 **/
8567		static inline T RawMask()
8568		{
8569			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8570			return 0;
8571		}
8572
8573		/** Get mask of bits used to store value.
8574		 *
8575		 * @return Mask
8576		 **/
8577		static inline T ValueMask()
8578		{
8579			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8580			return 0;
8581		}
8582
8583		/** Get offset.
8584		 *
8585		 * @return offset
8586		 **/
8587		static inline T Offset()
8588		{
8589			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8590			return 0;
8591		}
8592	};
8593
8594	/** Template class for accessing integer values stored in bit-fields
8595	 *
8596	 **/
8597	template <typename T, GLuint SIZE, GLuint OFFSET>
8598	class Integer
8599	{
8600	public:
8601		/** Constructor
8602		 *
8603		 **/
8604		Integer(T raw) : m_raw(raw)
8605		{
8606		}
8607
8608		/** Extract value from bit-field
8609		 *
8610		 * @return Value
8611		 **/
8612		T Get() const
8613		{
8614			const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8615
8616			const T bits   = m_raw & mask;
8617			const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8618
8619			return result;
8620		}
8621
8622		/** Extract value from bit-field and negate it
8623		 *
8624		 * @return Negated value
8625		 **/
8626		T GetNegated() const
8627		{
8628			const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8629			const T value = Get();
8630
8631			return Clamp((~value) + 1) & mask;
8632		}
8633
8634		T Clamp(T n) const
8635		{
8636			const bool isUnsigned = (T(0) < T(-1));
8637			const T	min		  = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8638			const T	max		  = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8639			const T	x		  = n > max ? max : n;
8640			return x < min ? min : x;
8641		}
8642
8643	private:
8644		T m_raw;
8645	};
8646
8647	/* Enums */
8648	/** Shader stage identification
8649	 *
8650	 **/
8651	enum shaderStage
8652	{
8653		fragmentShaderStage				 = 2,
8654		geometryShaderStage				 = 4,
8655		tesselationControlShaderStage	= 8,
8656		tesselationEvalutaionShaderStage = 16,
8657		vertexShaderStage				 = 32,
8658	};
8659
8660	/** Test result
8661	 *
8662	 **/
8663	enum testResult
8664	{
8665		testFailed		 = -1,
8666		testNotSupported = 1,
8667		testPassed		 = 0
8668	};
8669
8670	/* Constants */
8671	static const GLint m_min_required_image_uniforms = 2;
8672
8673	/* Fields */
8674	GLuint m_program_to_test_fs_stage_id;
8675	GLuint m_program_to_test_gs_stage_id;
8676	GLuint m_program_to_test_tcs_stage_id;
8677	GLuint m_program_to_test_tes_stage_id;
8678	GLuint m_program_to_test_vs_stage_id;
8679	GLuint m_texture_to_test_fs_stage_id;
8680	GLuint m_texture_to_test_gs_stage_id;
8681	GLuint m_texture_to_test_tcs_stage_id;
8682	GLuint m_texture_to_test_tes_stage_id;
8683	GLuint m_texture_to_test_vs_stage_id;
8684	GLuint m_vertex_array_object_id;
8685
8686public:
8687	/* Constructor */
8688	ImageLoadStoreMultipleUniformsTest()
8689		: m_program_to_test_fs_stage_id(0)
8690		, m_program_to_test_gs_stage_id(0)
8691		, m_program_to_test_tcs_stage_id(0)
8692		, m_program_to_test_tes_stage_id(0)
8693		, m_program_to_test_vs_stage_id(0)
8694		, m_texture_to_test_fs_stage_id(0)
8695		, m_texture_to_test_gs_stage_id(0)
8696		, m_texture_to_test_tcs_stage_id(0)
8697		, m_texture_to_test_tes_stage_id(0)
8698		, m_texture_to_test_vs_stage_id(0)
8699		, m_vertex_array_object_id(0)
8700	{
8701		/* Nothing to be done here */
8702	}
8703
8704	/* Methods inherited from SubcaseBase */
8705	virtual long Setup()
8706	{
8707		/* Prepare programs */
8708		m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8709		m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8710		m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8711		m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8712		m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8713
8714		/* Prepare textures */
8715		m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8716		m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8717		m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8718		m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8719		m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8720
8721		/* Generate vertex array object */
8722		glGenVertexArrays(1, &m_vertex_array_object_id);
8723		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8724
8725		/* Bind vertex array object */
8726		glBindVertexArray(m_vertex_array_object_id);
8727		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8728
8729		/* Set vertices number for patches */
8730		glPatchParameteri(GL_PATCH_VERTICES, 1);
8731
8732		/* Done */
8733		return NO_ERROR;
8734	}
8735
8736	virtual long Cleanup()
8737	{
8738		glUseProgram(0);
8739
8740		/* Delete programs */
8741		if (0 != m_program_to_test_fs_stage_id)
8742		{
8743			glDeleteProgram(m_program_to_test_fs_stage_id);
8744			m_program_to_test_fs_stage_id = 0;
8745		}
8746
8747		if (0 != m_program_to_test_gs_stage_id)
8748		{
8749			glDeleteProgram(m_program_to_test_gs_stage_id);
8750			m_program_to_test_gs_stage_id = 0;
8751		}
8752
8753		if (0 != m_program_to_test_tcs_stage_id)
8754		{
8755			glDeleteProgram(m_program_to_test_tcs_stage_id);
8756			m_program_to_test_tcs_stage_id = 0;
8757		}
8758
8759		if (0 != m_program_to_test_tes_stage_id)
8760		{
8761			glDeleteProgram(m_program_to_test_tes_stage_id);
8762			m_program_to_test_tes_stage_id = 0;
8763		}
8764
8765		if (0 != m_program_to_test_vs_stage_id)
8766		{
8767			glDeleteProgram(m_program_to_test_vs_stage_id);
8768			m_program_to_test_vs_stage_id = 0;
8769		}
8770
8771		/* Delete textures */
8772		if (0 != m_texture_to_test_fs_stage_id)
8773		{
8774			glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8775			m_texture_to_test_fs_stage_id = 0;
8776		}
8777
8778		if (0 != m_texture_to_test_gs_stage_id)
8779		{
8780			glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8781			m_texture_to_test_gs_stage_id = 0;
8782		}
8783
8784		if (0 != m_texture_to_test_tcs_stage_id)
8785		{
8786			glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8787			m_texture_to_test_tcs_stage_id = 0;
8788		}
8789
8790		if (0 != m_texture_to_test_tes_stage_id)
8791		{
8792			glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8793			m_texture_to_test_tes_stage_id = 0;
8794		}
8795
8796		if (0 != m_texture_to_test_vs_stage_id)
8797		{
8798			glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8799			m_texture_to_test_vs_stage_id = 0;
8800		}
8801
8802		/* Delete vertex array object id */
8803		if (0 != m_vertex_array_object_id)
8804		{
8805			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8806			m_vertex_array_object_id = 0;
8807		}
8808
8809		/* Done */
8810		return NO_ERROR;
8811	}
8812
8813	virtual long Run()
8814	{
8815		bool result = true;
8816
8817		if (testFailed == testShaderStage(fragmentShaderStage))
8818		{
8819			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8820												<< tcu::TestLog::EndMessage;
8821
8822			result = false;
8823		}
8824
8825		if (testFailed == testShaderStage(geometryShaderStage))
8826		{
8827			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8828												<< tcu::TestLog::EndMessage;
8829
8830			result = false;
8831		}
8832
8833		if (testFailed == testShaderStage(tesselationControlShaderStage))
8834		{
8835			m_context.getTestContext().getLog() << tcu::TestLog::Message
8836												<< "Problems with tesselation control shader stage!"
8837												<< tcu::TestLog::EndMessage;
8838
8839			result = false;
8840		}
8841
8842		if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8843		{
8844			m_context.getTestContext().getLog() << tcu::TestLog::Message
8845												<< "Problems with tesselation evaluation shader stage!"
8846												<< tcu::TestLog::EndMessage;
8847
8848			result = false;
8849		}
8850
8851		if (testFailed == testShaderStage(vertexShaderStage))
8852		{
8853			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8854												<< tcu::TestLog::EndMessage;
8855
8856			result = false;
8857		}
8858
8859		if (false == result)
8860		{
8861			return ERROR;
8862		}
8863
8864		/* Done */
8865		return NO_ERROR;
8866	}
8867
8868private:
8869	/* Static routines */
8870	/** Provide image format details for given index
8871	 *
8872	 * @param index       Index
8873	 * @param out_details Image format detail instance
8874	 **/
8875	static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8876	{
8877		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8878			"r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8879		};
8880
8881		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8882			{ "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8883			{ "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8884			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8885			{ "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8886			{ "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8887			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8888			{ "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8889			{ "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8890			{ "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8891			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8892			{ "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8893			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8894			{ "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8895			  ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8896			{ "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8897			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8898			{ "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8899			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8900			{ "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8901			{ "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8902			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8903			{ "rg16i", "iimage2D", "ivec4", GL_RG16I,
8904			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8905		};
8906
8907		static const GLuint n_imageUniformFormatDetails =
8908			sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8909
8910		if (n_imageUniformFormatDetails <= index)
8911		{
8912			out_details = default_format_details;
8913		}
8914		else
8915		{
8916			out_details = format_details[index];
8917		}
8918	}
8919
8920	/** Write name of image uniform at given index to output stream
8921	 *
8922	 * @param stream Output stream
8923	 * @param index  Index
8924	 **/
8925	static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
8926	{
8927		/* u_image_0 */
8928		stream << "u_image_" << index;
8929	}
8930
8931	/** Write name of variable used to store value loaded from image at given index to output stream
8932	 *
8933	 * @param stream Output stream
8934	 * @param index  Index
8935	 **/
8936	static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
8937	{
8938		/* loaded_value_0 */
8939		stream << "loaded_value_" << index;
8940	}
8941
8942	/** Write name of variable used to store coordinate of texel at given row to output stream
8943	 *
8944	 * @param stream Output stream
8945	 * @param index  Index of image uniform
8946	 * @param row    Row of image
8947	 **/
8948	static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
8949	{
8950		/* row_0_coordinates_0 */
8951		stream << "row_" << row << "_coordinates_" << index;
8952	}
8953
8954	struct imageUniformDeclaration
8955	{
8956		imageUniformDeclaration(GLuint index) : m_index(index)
8957		{
8958		}
8959
8960		GLuint m_index;
8961	};
8962
8963	/** Write declaration of image uniform at given index to output stream
8964	 *
8965	 * @param stream                   Output stream
8966	 * @param imageUniformDeclaration  Declaration details
8967	 *
8968	 * @return stream
8969	 **/
8970	friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
8971	{
8972		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
8973		getImageUniformDeclarationDetails(declaration.m_index, format_details);
8974
8975		/* layout(r32f) uniform image2D u_image_0; */
8976		stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
8977
8978		ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
8979
8980		stream << ";";
8981
8982		return stream;
8983	}
8984
8985	struct imageLoadCall
8986	{
8987		imageLoadCall(GLuint index) : m_index(index)
8988		{
8989		}
8990
8991		GLuint m_index;
8992	};
8993
8994	/* Stream operators */
8995	/** Write code that execute imageLoad routine for image at given index to output stream
8996	 *
8997	 * @param stream Output stream
8998	 * @param load   imageLoad call details
8999	 *
9000	 * @return stream
9001	 **/
9002	friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9003	{
9004		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9005		getImageUniformDeclarationDetails(load.m_index, format_details);
9006
9007		/* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9008		stream << format_details.m_color_type << " ";
9009
9010		writeLoadedValueVariableNameToStream(stream, load.m_index);
9011
9012		stream << " = imageLoad(";
9013
9014		writeImageUniformNameToStream(stream, load.m_index);
9015
9016		stream << ", ";
9017
9018		writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9019
9020		stream << ");";
9021
9022		return stream;
9023	}
9024
9025	struct imageStoreCall
9026	{
9027		imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9028		{
9029		}
9030
9031		GLuint m_index;
9032		GLuint m_row;
9033	};
9034
9035	/** Write code that execute imageStore to image at given index to output stream
9036	 *
9037	 * @param stream Output stream
9038	 * @param store  imageStore call details
9039	 *
9040	 * @return stream
9041	 **/
9042	friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9043	{
9044		/* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9045		stream << "imageStore(";
9046
9047		writeImageUniformNameToStream(stream, store.m_index);
9048
9049		stream << ", ";
9050
9051		writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9052
9053		if (0 == store.m_row)
9054		{
9055			stream << ", -";
9056		}
9057		else
9058		{
9059			stream << ", ";
9060		}
9061
9062		writeLoadedValueVariableNameToStream(stream, store.m_index);
9063		stream << ");";
9064
9065		return stream;
9066	}
9067
9068	struct coordinatesVariableDeclaration
9069	{
9070		coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9071		{
9072		}
9073		GLuint m_index;
9074		GLuint m_row;
9075	};
9076
9077	/** Write declaration of variable for coordinate at given row to output stream
9078	 *
9079	 * @param stream      Output stream
9080	 * @param declaration Declaration details
9081	 *
9082	 * @return stream
9083	 **/
9084	friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9085	{
9086		stream << "const ivec2 ";
9087
9088		writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9089
9090		stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9091
9092		return stream;
9093	}
9094
9095	/* Methods */
9096	/** Build program to test specified shader stage
9097	 *
9098	 * Throws exception in case of any failure
9099	 *
9100	 * @param stage Stage id
9101	 *
9102	 * @return Program id
9103	 **/
9104	GLuint buildProgramToTestShaderStage(shaderStage stage)
9105	{
9106		static const char* const boilerplate_fragment_shader_code =
9107			"#version 400 core\n"
9108			"#extension GL_ARB_shader_image_load_store : require\n"
9109			"\n"
9110			"precision highp float;\n"
9111			"\n"
9112			"void main()\n"
9113			"{\n"
9114			"    discard;\n"
9115			"}\n";
9116
9117		static const char* const boilerplate_tesselation_evaluation_shader_code =
9118			"#version 400 core\n"
9119			"#extension GL_ARB_shader_image_load_store : require\n"
9120			"\n"
9121			"precision highp float;\n"
9122			"\n"
9123			"layout(quads, equal_spacing, ccw) in;\n"
9124			"\n"
9125			"void main()\n"
9126			"{\n"
9127			"\n"
9128			"}\n";
9129
9130		static const char* const boilerplate_vertex_shader_code =
9131			"#version 400 core\n"
9132			"#extension GL_ARB_shader_image_load_store : require\n"
9133			"\n"
9134			"precision highp float;\n"
9135			"\n"
9136			"layout(location = 0) in vec4 i_position;\n"
9137			"\n"
9138			"void main()\n"
9139			"{\n"
9140			"  gl_Position = i_position;\n"
9141			"}\n";
9142
9143		const char* fragment_shader_code			   = boilerplate_fragment_shader_code;
9144		const char* geometry_shader_code			   = 0;
9145		bool		is_program_built				   = true;
9146		GLuint		program_object_id				   = 0;
9147		const char* tesselation_control_shader_code	= 0;
9148		const char* tesselation_evaluation_shader_code = 0;
9149		std::string tested_shader_stage_code;
9150		const char* vertex_shader_code = boilerplate_vertex_shader_code;
9151
9152		/* Get source code for tested shader stage */
9153		prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9154
9155		if (true == tested_shader_stage_code.empty())
9156		{
9157			return 0;
9158		}
9159
9160		/* Set up source code for all required stages */
9161		switch (stage)
9162		{
9163		case fragmentShaderStage:
9164			fragment_shader_code = tested_shader_stage_code.c_str();
9165			break;
9166
9167		case geometryShaderStage:
9168			geometry_shader_code = tested_shader_stage_code.c_str();
9169			break;
9170
9171		case tesselationControlShaderStage:
9172			tesselation_control_shader_code	= tested_shader_stage_code.c_str();
9173			tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9174			break;
9175
9176		case tesselationEvalutaionShaderStage:
9177			tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9178			break;
9179
9180		case vertexShaderStage:
9181			vertex_shader_code = tested_shader_stage_code.c_str();
9182			break;
9183
9184		default:
9185			TCU_FAIL("Invalid shader stage");
9186		}
9187
9188		/* Build program */
9189		program_object_id =
9190			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9191						 geometry_shader_code, fragment_shader_code, &is_program_built);
9192
9193		/* Check if program was built */
9194		if (false == is_program_built)
9195		{
9196			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9197		}
9198
9199		/* Done */
9200		return program_object_id;
9201	}
9202
9203	/** Create texture to test given shader stage
9204	 *
9205	 * Throws exception in case of any failure
9206	 *
9207	 * @param stage Stage id
9208	 *
9209	 * @return Texture id
9210	 **/
9211	GLuint createTextureToTestShaderStage(shaderStage stage)
9212	{
9213		GLenum			   error			  = glGetError();
9214		const GLint		   max_image_uniforms = getMaximumImageUniformsForStage(stage);
9215		GLuint			   texture_id		  = 0;
9216		std::vector<GLint> texture_data;
9217
9218		const GLsizei height = 2;
9219		const GLsizei width  = max_image_uniforms;
9220
9221		if (m_min_required_image_uniforms > max_image_uniforms)
9222		{
9223			return 0;
9224		}
9225
9226		/* Generate texture id */
9227		glGenTextures(1, &texture_id);
9228		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9229
9230		/* Bind texture */
9231		glBindTexture(GL_TEXTURE_2D, texture_id);
9232		error = glGetError();
9233		if (GL_NO_ERROR != error)
9234		{
9235			glDeleteTextures(1, &texture_id);
9236			GLU_EXPECT_NO_ERROR(error, "BindTexture");
9237		}
9238
9239		/* Prepare storage for texture data */
9240		texture_data.resize(width * height);
9241		for (GLint i = 0; i < max_image_uniforms; ++i)
9242		{
9243			texture_data[i]			= getExpectedValue(i);
9244			texture_data[i + width] = 0;
9245		}
9246
9247		/* Create first level of texture */
9248		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9249					 &texture_data[0]);
9250		error = glGetError();
9251		if (GL_NO_ERROR != error)
9252		{
9253			glDeleteTextures(1, &texture_id);
9254			GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9255		}
9256
9257		/* Make texture complete */
9258		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9259		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9260		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9261		error = glGetError();
9262		if (GL_NO_ERROR != error)
9263		{
9264			glDeleteTextures(1, &texture_id);
9265			GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9266		}
9267
9268		/* Done */
9269		return texture_id;
9270	}
9271
9272	/** Get value of texel for image at given index
9273	 *
9274	 * @param index Index of image uniform
9275	 *
9276	 * @return Value of texel
9277	 **/
9278	GLint getExpectedValue(GLint index)
9279	{
9280		// To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9281		// we set one bit in the exponent of each component of those pixel format
9282		return 0x40104200 + index;
9283	}
9284
9285	/** Get name of uniform at given index
9286	 *
9287	 * @param index    Index of uniform
9288	 * @param out_name Name of uniform
9289	 **/
9290	void getImageUniformName(GLuint index, std::string& out_name)
9291	{
9292		std::stringstream stream;
9293
9294		writeImageUniformNameToStream(stream, index);
9295
9296		out_name = stream.str();
9297	}
9298
9299	/** Get maximum number of image uniforms allowed for given shader stage
9300	 *
9301	 * @param stage Stage id
9302	 *
9303	 * @return Maximum allowed image uniforms
9304	 **/
9305	GLint getMaximumImageUniformsForStage(shaderStage stage)
9306	{
9307		GLint  max_image_uniforms = 0;
9308		GLenum pname			  = 0;
9309
9310		switch (stage)
9311		{
9312		case fragmentShaderStage:
9313			pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9314			break;
9315
9316		case geometryShaderStage:
9317			pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9318			break;
9319
9320		case tesselationControlShaderStage:
9321			pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9322			break;
9323
9324		case tesselationEvalutaionShaderStage:
9325			pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9326			break;
9327
9328		case vertexShaderStage:
9329			pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9330			break;
9331
9332		default:
9333			TCU_FAIL("Invalid shader stage");
9334		}
9335
9336		glGetIntegerv(pname, &max_image_uniforms);
9337		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9338
9339		return max_image_uniforms;
9340	}
9341
9342	/** Prepare source for tested shader stage
9343	 *
9344	 * @param stage    Stage id
9345	 * @param out_code Source code
9346	 **/
9347	void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9348	{
9349		GLint			  max_image_uniforms	= getMaximumImageUniformsForStage(stage);
9350		const char*		  stage_specific_layout = "";
9351		const char*		  stage_specific_predicate = "true";
9352		std::stringstream stream;
9353
9354		if (m_min_required_image_uniforms > max_image_uniforms)
9355		{
9356			return;
9357		}
9358
9359		/* Expected result follows
9360		 *
9361		 * #version 400 core
9362		 * #extension GL_ARB_shader_image_load_store : require
9363		 *
9364		 * precision highp float;
9365		 *
9366		 * stage_specific_layout goes here
9367		 *
9368		 * Uniform declarations go here
9369		 *
9370		 * void main()
9371		 * {
9372		 *     const ivec2 row_0_coordinates(0, 0);
9373		 *     const ivec2 row_1_coordinates(0, 1);
9374		 *
9375		 *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9376		 *
9377		 *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9378		 *
9379		 *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9380		 *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9381		 * }
9382		 */
9383
9384		/* Get piece of code specific for stage */
9385		switch (stage)
9386		{
9387		case fragmentShaderStage:
9388			break;
9389
9390		case geometryShaderStage:
9391			stage_specific_layout = "layout(points) in;\n"
9392									"layout(points, max_vertices = 1) out;\n"
9393									"\n";
9394			break;
9395
9396		case tesselationControlShaderStage:
9397			stage_specific_layout = "layout(vertices = 4) out;\n"
9398									"\n";
9399			stage_specific_predicate = "gl_InvocationID == 0";
9400			break;
9401
9402		case tesselationEvalutaionShaderStage:
9403			stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9404									"\n";
9405			break;
9406
9407		case vertexShaderStage:
9408			break;
9409
9410		default:
9411			TCU_FAIL("Invalid shader stage");
9412		}
9413
9414		/* Preamble */
9415		stream << "#version 400 core\n"
9416				  "#extension GL_ARB_shader_image_load_store : require\n"
9417				  "\n"
9418				  "precision highp float;\n"
9419				  "\n"
9420			   << stage_specific_layout;
9421
9422		/* Image uniforms declarations */
9423		for (GLint i = 0; i < max_image_uniforms; ++i)
9424		{
9425			stream << imageUniformDeclaration(i) << "\n";
9426		}
9427
9428		/* Main opening */
9429		stream << "\n"
9430				  "void main()\n"
9431				  "{\n";
9432
9433		stream << "    if (" << stage_specific_predicate << ")\n";
9434		stream << "    {\n";
9435
9436		/* imageLoad and imageStores for each uniform */
9437		for (GLint i = 0; i < max_image_uniforms; ++i)
9438		{
9439			stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9440				   << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9441				   << "\n"
9442				   << "        " << imageLoadCall(i) << "\n"
9443				   << "\n"
9444				   << "        " << imageStoreCall(i, 0) << "\n"
9445				   << "        " << imageStoreCall(i, 1) << "\n";
9446
9447			if (max_image_uniforms > i + 1)
9448			{
9449				stream << "\n";
9450			}
9451		}
9452
9453		stream << "    }\n";
9454
9455		/* Main closing */
9456		stream << "}\n\n";
9457
9458		/* Done */
9459		out_code = stream.str();
9460	}
9461
9462	/** Test given shader stage
9463	 *
9464	 * @param stage Stage id
9465	 *
9466	 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9467	 *         testFailed when test result is negative;
9468	 *         m_test_passed when test result is positive;
9469	 **/
9470	testResult testShaderStage(shaderStage stage)
9471	{
9472		std::string		   image_uniform_name;
9473		static const GLint invalid_uniform_location = -1;
9474		const GLint		   max_image_uniforms		= getMaximumImageUniformsForStage(stage);
9475		GLenum			   primitive_mode			= GL_POINTS;
9476		GLuint			   program_id				= 0;
9477		testResult		   result					= testPassed;
9478		std::vector<GLint> texture_data;
9479		GLuint			   texture_id = 0;
9480
9481		static const GLuint height = 2;
9482		const GLuint		width  = max_image_uniforms;
9483
9484		const GLuint		positive_value_index = width;
9485		static const GLuint negated_value_index  = 0;
9486
9487		if (m_min_required_image_uniforms > max_image_uniforms)
9488		{
9489			return testNotSupported;
9490		}
9491
9492		/* Select program and texture ids for given stage */
9493		switch (stage)
9494		{
9495		case fragmentShaderStage:
9496			program_id = m_program_to_test_fs_stage_id;
9497			texture_id = m_texture_to_test_fs_stage_id;
9498			break;
9499
9500		case geometryShaderStage:
9501			program_id = m_program_to_test_gs_stage_id;
9502			texture_id = m_texture_to_test_gs_stage_id;
9503			break;
9504
9505		case tesselationControlShaderStage:
9506			primitive_mode = GL_PATCHES;
9507			program_id	 = m_program_to_test_tcs_stage_id;
9508			texture_id	 = m_texture_to_test_tcs_stage_id;
9509			break;
9510
9511		case tesselationEvalutaionShaderStage:
9512			primitive_mode = GL_PATCHES;
9513			program_id	 = m_program_to_test_tes_stage_id;
9514			texture_id	 = m_texture_to_test_tes_stage_id;
9515			break;
9516
9517		case vertexShaderStage:
9518			program_id = m_program_to_test_vs_stage_id;
9519			texture_id = m_texture_to_test_vs_stage_id;
9520			break;
9521
9522		default:
9523			TCU_FAIL("Invalid shader stage");
9524		}
9525
9526		/* Set program */
9527		glUseProgram(program_id);
9528		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9529
9530		/* Bind texture to image units */
9531		for (GLint i = 0; i < max_image_uniforms; ++i)
9532		{
9533			imageFormatDetails format_details;
9534			getImageUniformDeclarationDetails(i, format_details);
9535
9536			glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9537							   GL_READ_WRITE, format_details.m_image_unit_format);
9538			GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9539		}
9540
9541		/* Set all image uniforms to corresponding image units */
9542		for (GLint i = 0; i < max_image_uniforms; ++i)
9543		{
9544			/* Get name */
9545			getImageUniformName(i, image_uniform_name);
9546
9547			/* Get location */
9548			GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9549			GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9550
9551			if (invalid_uniform_location == image_uniform_location)
9552			{
9553				throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9554										 __LINE__);
9555			}
9556
9557			/* Set uniform value */
9558			glUniform1i(image_uniform_location, i /* image_unit */);
9559			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9560		}
9561
9562		/* Execute draw */
9563		glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9564		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9565
9566		glMemoryBarrier(GL_ALL_BARRIER_BITS);
9567
9568		texture_data.resize(width * height);
9569
9570		/* Get texture data */
9571		glBindTexture(GL_TEXTURE_2D, texture_id);
9572		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9573
9574		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9575		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9576
9577		/* Verify each image uniform */
9578		for (GLint i = 0; i < max_image_uniforms; ++i)
9579		{
9580			imageFormatDetails format_details;
9581			getImageUniformDeclarationDetails(i, format_details);
9582
9583			if (false ==
9584				format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9585													  texture_data[negated_value_index + i]))
9586			{
9587				m_context.getTestContext().getLog()
9588					<< tcu::TestLog::Message << "Invalid result!"
9589					<< " Image format: " << format_details.m_image_format << " Original value: "
9590					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9591					<< " Copied value: "
9592					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9593					<< texture_data[positive_value_index + i] << " Negated value: "
9594					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9595					<< texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9596
9597				result = testFailed;
9598			}
9599		}
9600
9601		/* Done */
9602		return result;
9603	}
9604
9605	/** Verifies if original_value, positive_value and negated_value match
9606	 *
9607	 * @tparam T Type used during verification process, it should match float values by size
9608	 *
9609	 * @param original_value Original value of texel, used when creating a texture
9610	 * @param positive_value Value stored by shader as read
9611	 * @param negated_value  Value stored by shader after negation
9612	 *
9613	 * @return true if values match, false otherwise
9614	 **/
9615	template <typename T>
9616	static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9617	{
9618		if (original_value != positive_value)
9619		{
9620			return false;
9621		}
9622
9623		static const GLuint n_elements		  = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9624		static const GLuint sign_bit_index	= sizeof(T) * 8 - 1;		   /* 7, 15, 31 */
9625		static const T		sign_bit_mask	 = 1 << sign_bit_index;	   /* 0x80.. */
9626		static const T		sign_bit_inv_mask = (T)~sign_bit_mask;		   /* 0x7f.. */
9627
9628		const T* positive_elements = (T*)&positive_value;
9629		const T* negated_elements  = (T*)&negated_value;
9630
9631		for (GLuint i = 0; i < n_elements; ++i)
9632		{
9633			const T positive_element = positive_elements[i];
9634			const T negated_element  = negated_elements[i];
9635
9636			const T positive_sign_bit = positive_element & sign_bit_mask;
9637			const T negated_sign_bit  = negated_element & sign_bit_mask;
9638
9639			const T positive_data = positive_element & sign_bit_inv_mask;
9640			const T negated_data  = negated_element & sign_bit_inv_mask;
9641
9642			/* Compare data bits */
9643			if (positive_data != negated_data)
9644			{
9645				return false;
9646			}
9647
9648			/* Verify that sign bit is inverted */
9649			if (positive_sign_bit == negated_sign_bit)
9650			{
9651				return false;
9652			}
9653		}
9654
9655		return true;
9656	}
9657
9658	/** Verifies if original_value, positive_value and negated_value match
9659	 *
9660	 * @tparam T Type used during verification process, it should match float values by size
9661	 *
9662	 * @param original_value Original value of texel, used when creating a texture
9663	 * @param positive_value Value stored by shader as read
9664	 * @param negated_value  Value stored by shader after negation
9665	 *
9666	 * @return true if values match, false otherwise
9667	 **/
9668	template <typename T>
9669	static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9670	{
9671		if (original_value != positive_value)
9672		{
9673			return false;
9674		}
9675
9676		static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9677
9678		const T* positive_elements = (T*)&positive_value;
9679		const T* negated_elements  = (T*)&negated_value;
9680
9681		for (GLuint i = 0; i < n_elements; ++i)
9682		{
9683			const T positive_element = positive_elements[i];
9684			const T negated_element  = negated_elements[i];
9685
9686			/* Compare data bits */
9687			if (positive_element != -negated_element)
9688			{
9689				return false;
9690			}
9691		}
9692
9693		return true;
9694	}
9695
9696	/** Verifies if original_value, positive_value and negated_value match
9697	 *
9698	 * @tparam R Number of bits for red channel
9699	 * @tparam G Number of bits for green channel
9700	 * @tparam B Number of bits for blue channel
9701	 * @tparam A Number of bits for alpha channel
9702	 *
9703	 * @param original_value Original value of texel, used when creating a texture
9704	 * @param positive_value Value stored by shader as read
9705	 * @param negated_value  Value stored by shader after negation
9706	 *
9707	 * @return true if values match, false otherwise
9708	 **/
9709	template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
9710	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9711	{
9712		if (original_value != positive_value)
9713		{
9714			return false;
9715		}
9716
9717		Integer<T, R, 0> positive_red(positive_value);
9718		Integer<T, R, 0> negated_red(negated_value);
9719
9720		Integer<T, G, R> positive_green(positive_value);
9721		Integer<T, G, R> negated_green(negated_value);
9722
9723		Integer<T, B, R + G> positive_blue(positive_value);
9724		Integer<T, B, R + G> negated_blue(negated_value);
9725
9726		Integer<T, A, R + G + B> positive_alpha(positive_value);
9727		Integer<T, A, R + G + B> negated_alpha(negated_value);
9728
9729		if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9730			((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9731			((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9732			((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9733		{
9734			return false;
9735		}
9736
9737		return true;
9738	}
9739
9740	/** Verifies if original_value, positive_value and negated_value match
9741	 *
9742	 * @param original_value Original value of texel, used when creating a texture
9743	 * @param positive_value Value stored by shader as read
9744	 * @param negated_value  Value stored by shader after negation
9745	 *
9746	 * @return true if values match, false otherwise
9747	 **/
9748	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9749	{
9750		if (original_value != positive_value)
9751		{
9752			return false;
9753		}
9754
9755		if (positive_value != -negated_value)
9756		{
9757			return false;
9758		}
9759
9760		return true;
9761	}
9762
9763	/** Verifies if original_value, positive_value and negated_value match
9764	 *
9765	 * @param original_value Original value of texel, used when creating a texture
9766	 * @param positive_value Value stored by shader as read
9767	 * @param negated_value  Value stored by shader after negation
9768	 *
9769	 * @return true if values match, false otherwise
9770	 **/
9771	template <typename T>
9772	static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9773	{
9774		if (original_value != positive_value)
9775		{
9776			return false;
9777		}
9778
9779		if (0 != negated_value)
9780		{
9781			return false;
9782		}
9783
9784		return true;
9785	}
9786};
9787
9788/** Test "Early fragment tests" description follows.
9789 *
9790 *  BasicGLSLEarlyFragTests verifies that:
9791 *  - early z test is applied when enabled,
9792 *  - early z test is not applied when disabled.
9793 *
9794 *  Proposed modifications:
9795 *  - verify that early z test does not discard all fragments when enabled,
9796 *  - verify that early stencil test is applied when enabled,
9797 *  - verify that early stencil test does not discard all fragments when
9798 *  enabled,
9799 *  - verify that early stencil test is not applied when disabled.
9800 *
9801 *  Steps:
9802 *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9803 *  shader stage:
9804 *      a) one program should enable early fragment tests
9805 *      ("layout(early_fragment_tests) in;"),
9806 *      b) second program should disable early fragment tests,
9807 *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9808 *  depth-stencil attachments,
9809 *  - prepare 2D texture 64x64 R32F,
9810 *  - enable depth test,
9811 *  - verify that early z test is applied when enabled:
9812 *      - use program enabling early fragment tests,
9813 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9814 *      - fill texture with zeros,
9815 *      - bind texture to image uniform,
9816 *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9817 *      corner at 1,1) at z: 0.75
9818 *      - verify that texture is still filled with zeros,
9819 *  - verify that early z test does not discard all fragments:
9820 *      - use program enabling early fragment tests,
9821 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9822 *      - fill texture with zeros,
9823 *      - bind texture to image uniform,
9824 *      - draw "full screen" quad at z: 0.25
9825 *      - verify that texture is now filled with 1.0,
9826 *  -verify that early z test is not applied when disabled:
9827 *      - use program disabling early fragment tests,
9828 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9829 *      - fill texture with zeros,
9830 *      - bind texture to image uniform,
9831 *      - draw "full screen" quad at z: 0.75
9832 *      - verify that texture is now filled with 1.0.
9833 *  - disable depth test
9834 *  - enable stencil test
9835 *  - verify that early stencil test is applied when enabled:
9836 *      - use program enabling early fragment tests,
9837 *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9838 *      - fill texture with zeros,
9839 *      - set stencil test to:
9840 *          - <func> to GL_LESS,
9841 *          - <ref> to 128,
9842 *          - <mask> 0xffffffff,
9843 *      - bind texture to image uniform,
9844 *      - draw "full screen" quad at z: 0,
9845 *      - verify that texture is still filled with zeros,
9846 *  - verify that early stencil test does not discard all fragments:
9847 *      - use program enabling early fragment tests,
9848 *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9849 *      - fill texture with zeros,
9850 *      - set stencil test to:
9851 *          - <func> to GL_LESS,
9852 *          - <ref> to 0,
9853 *          - <mask> 0xffffffff,
9854 *      - bind texture to image uniform,
9855 *      - draw "full screen" quad at z: 0,
9856 *      - verify that texture is now filled with 1.0,
9857 *  - verify that early stencil test is not applied when disabled:
9858 *      - use program disabling early fragment tests,
9859 *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9860 *      - fill texture with zeros,
9861 *      - set stencil test to:
9862 *          - <func> to GL_LESS,
9863 *          - <ref> to 128,
9864 *          - <mask> 0xffffffff,
9865 *      - bind texture to image uniform,
9866 *      - draw "full screen" quad at z: 0,
9867 *      - verify that texture is now filled with 1.0
9868 **/
9869class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9870{
9871private:
9872	/* Constants */
9873	GLuint			   m_image_edge;
9874	static const GLint m_invalid_uniform_location = -1;
9875
9876	/* Types */
9877	/** Store id and uniform locations for a single program object
9878	 *
9879	 **/
9880	struct programDetails
9881	{
9882		GLint  m_depth_uniform_location;
9883		GLint  m_image_uniform_location;
9884		GLuint m_program_id;
9885
9886		programDetails()
9887			: m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9888			, m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9889			, m_program_id(0)
9890		{
9891			/* Nothing to be done here */
9892		}
9893	};
9894
9895	/* Fileds */
9896	/* Storage for texture data */
9897	std::vector<GLfloat> m_clean_texture_data;
9898	std::vector<GLfloat> m_extracted_texture_data;
9899
9900	/* Program details */
9901	programDetails m_disabled_early_tests;
9902	programDetails m_enabled_early_tests;
9903
9904	/* Ids of GL objects */
9905	GLuint m_color_renderbuffer_id;
9906	GLuint m_depth_stencil_renderbuffer_id;
9907	GLuint m_framebuffer_id;
9908	GLuint m_texture_id;
9909	GLuint m_vertex_array_object_id;
9910
9911public:
9912	/* Constructor */
9913	ImageLoadStoreEarlyFragmentTestsTest()
9914		: m_image_edge(0)
9915		, m_color_renderbuffer_id(0)
9916		, m_depth_stencil_renderbuffer_id(0)
9917		, m_framebuffer_id(0)
9918		, m_texture_id(0)
9919		, m_vertex_array_object_id(0)
9920	{
9921		/* Nothing to be done here */
9922	}
9923
9924	/* Methods inherited from SubcaseBase */
9925	virtual long Cleanup()
9926	{
9927		/* Restore defaults */
9928		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
9929		glBindRenderbuffer(GL_RENDERBUFFER, 0);
9930		glBindTexture(GL_TEXTURE_2D, 0);
9931		glBindVertexArray(0);
9932		glDisable(GL_DEPTH_TEST);
9933		glDisable(GL_STENCIL_TEST);
9934		glUseProgram(0);
9935
9936		/* Delete objects */
9937		if (0 != m_disabled_early_tests.m_program_id)
9938		{
9939			glDeleteProgram(m_disabled_early_tests.m_program_id);
9940			m_disabled_early_tests.m_program_id = 0;
9941		}
9942
9943		if (0 != m_enabled_early_tests.m_program_id)
9944		{
9945			glDeleteProgram(m_enabled_early_tests.m_program_id);
9946			m_enabled_early_tests.m_program_id = 0;
9947		}
9948
9949		if (0 != m_color_renderbuffer_id)
9950		{
9951			glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
9952			m_color_renderbuffer_id = 0;
9953		}
9954
9955		if (0 != m_depth_stencil_renderbuffer_id)
9956		{
9957			glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
9958			m_depth_stencil_renderbuffer_id = 0;
9959		}
9960
9961		if (0 != m_framebuffer_id)
9962		{
9963			glDeleteFramebuffers(1, &m_framebuffer_id);
9964			m_framebuffer_id = 0;
9965		}
9966
9967		if (0 != m_texture_id)
9968		{
9969			glDeleteTextures(1, &m_texture_id);
9970			m_texture_id = 0;
9971		}
9972
9973		if (0 != m_vertex_array_object_id)
9974		{
9975			glDeleteVertexArrays(1, &m_vertex_array_object_id);
9976			m_vertex_array_object_id = 0;
9977		}
9978
9979		/* Done */
9980		return NO_ERROR;
9981	}
9982
9983	virtual long Run()
9984	{
9985		bool result = true;
9986
9987		/* Bind texture to first image unit */
9988		glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9989						   GL_READ_WRITE, GL_R32F);
9990		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9991
9992		/* Run tests for depth test */
9993		if (false == testEarlyZ())
9994		{
9995			result = false;
9996		}
9997
9998		/* Run tests for stencil test */
9999		if (false == testEarlyStencil())
10000		{
10001			result = false;
10002		}
10003
10004		/* Return ERROR if any problem was found */
10005		if (false == result)
10006		{
10007			return ERROR;
10008		}
10009
10010		/* Done */
10011		return NO_ERROR;
10012	}
10013
10014	virtual long Setup()
10015	{
10016		m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10017
10018		/* Prepare storage for texture data */
10019		m_clean_texture_data.resize(m_image_edge * m_image_edge);
10020		m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10021
10022		/* Prepare programs, framebuffer and texture */
10023		buildPrograms();
10024		createFramebuffer();
10025		createTexture();
10026
10027		/* Generate vertex array object */
10028		glGenVertexArrays(1, &m_vertex_array_object_id);
10029		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10030
10031		/* Bind vertex array object */
10032		glBindVertexArray(m_vertex_array_object_id);
10033		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10034
10035		/* Set clear color */
10036		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10037		GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10038
10039		/* Done */
10040		return NO_ERROR;
10041	}
10042
10043private:
10044	/** Build two programs: with enabled and disabled early fragment tests
10045	 *
10046	 **/
10047	void buildPrograms()
10048	{
10049		static const char* const fragment_shader_with_disabled_early_tests =
10050			"#version 400 core\n"
10051			"#extension GL_ARB_shader_image_load_store : require\n"
10052			"\n"
10053			"precision highp float;\n"
10054			"\n"
10055			"layout(r32f) uniform image2D u_image;\n"
10056			"\n"
10057			"void main()\n"
10058			"{\n"
10059			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10060			"\n"
10061			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10062			"\n"
10063			"    discard;\n"
10064			"}\n\n";
10065
10066		static const char* const fragment_shader_with_enabled_early_tests =
10067			"#version 400 core\n"
10068			"#extension GL_ARB_shader_image_load_store : require\n"
10069			"\n"
10070			"precision highp float;\n"
10071			"\n"
10072			"layout(early_fragment_tests) in;\n"
10073			"\n"
10074			"layout(r32f) uniform image2D u_image;\n"
10075			"\n"
10076			"void main()\n"
10077			"{\n"
10078			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10079			"\n"
10080			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10081			"\n"
10082			"    discard;\n"
10083			"}\n\n";
10084
10085		static const char* const geometry_shader_code = "#version 400 core\n"
10086														"#extension GL_ARB_shader_image_load_store : require\n"
10087														"\n"
10088														"precision highp float;\n"
10089														"\n"
10090														"layout(points)                           in;\n"
10091														"layout(triangle_strip, max_vertices = 4) out;\n"
10092														"\n"
10093														"uniform float u_depth;\n"
10094														"\n"
10095														"void main()\n"
10096														"{\n"
10097														"    // Left-bottom\n"
10098														"    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10099														"    EmitVertex();\n"
10100														"\n"
10101														"    // Left-top\n"
10102														"    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10103														"    EmitVertex();\n"
10104														"\n"
10105														"    // Right-bottom\n"
10106														"    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10107														"    EmitVertex();\n"
10108														"\n"
10109														"    // Right-top\n"
10110														"    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10111														"    EmitVertex();\n"
10112														"}\n\n";
10113
10114		static const char* const vertex_shader_code = "#version 400 core\n"
10115													  "#extension GL_ARB_shader_image_load_store : require\n"
10116													  "\n"
10117													  "precision highp float;\n"
10118													  "\n"
10119													  "void main()\n"
10120													  "{\n"
10121													  "}\n\n";
10122
10123		prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10124							  m_disabled_early_tests);
10125
10126		prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10127							  m_enabled_early_tests);
10128	}
10129
10130	/** Fill texture with zeros
10131	 *
10132	 **/
10133	void cleanTexture()
10134	{
10135		glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10136						GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10137		GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10138	}
10139
10140	/** Create and bind (draw) framebuffer with color and depth-stencil attachments
10141	 *
10142	 **/
10143	void createFramebuffer()
10144	{
10145		/* Generate render buffers */
10146		glGenRenderbuffers(1, &m_color_renderbuffer_id);
10147		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10148
10149		glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10150		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10151
10152		/* Generate and bind framebuffer object */
10153		glGenFramebuffers(1, &m_framebuffer_id);
10154		GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10155
10156		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10157		GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10158
10159		/* Prepare color render buffer */
10160		glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10161		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10162
10163		glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10164		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10165
10166		/* Set up color attachment */
10167		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10168		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10169
10170		/* Prepare depth-stencil render buffer */
10171		glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10172		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10173
10174		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10175		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10176
10177		/* Set up depth-stencil attachment */
10178		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10179								  m_depth_stencil_renderbuffer_id);
10180		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10181	}
10182
10183	/** Create 2D R32F texture
10184	 *
10185	 **/
10186	void createTexture()
10187	{
10188		glGenTextures(1, &m_texture_id);
10189		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10190
10191		glBindTexture(GL_TEXTURE_2D, m_texture_id);
10192		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10193
10194		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10195		GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10196	}
10197
10198	/** Extracts red channel from texture and verify if all texels are set to specified value
10199	 *
10200	 * @param value Expected value
10201	 *
10202	 * @return true if all texel match expected value, false otherwise
10203	 **/
10204	bool isTextureFilledWithValue(GLfloat value)
10205	{
10206		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10207		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10208
10209		for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10210		{
10211			if (value != m_extracted_texture_data[i])
10212			{
10213				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10214													<< " has invalid value: " << m_extracted_texture_data[i]
10215													<< " expected: " << value << tcu::TestLog::EndMessage;
10216
10217				return false;
10218			}
10219		}
10220
10221		return true;
10222	}
10223
10224	/** Build program, extract location of uniforms and store results in programDetails instance
10225	 *
10226	 * Throws tcu::InternalError if uniforms are inactive
10227	 *
10228	 * @param fragment_shader_code Source of fragment shader
10229	 * @param geometry_shader_code Source of geometry shader
10230	 * @param vertex_shader_code   Source of vertex shader
10231	 * @param out_program_details  Instance of programDetails
10232	 **/
10233	void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10234							   const char* vertex_shader_code, programDetails& out_program_details)
10235	{
10236		static const char* const depth_uniform_name = "u_depth";
10237		static const char* const image_uniform_name = "u_image";
10238		bool					 is_program_built   = true;
10239
10240		GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10241										 fragment_shader_code, &is_program_built);
10242
10243		if (false == is_program_built)
10244		{
10245			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10246		}
10247
10248		/* Get depth uniform location */
10249		GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10250		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10251
10252		if (m_invalid_uniform_location == depth_uniform_location)
10253		{
10254			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10255		}
10256
10257		/* Get image uniform location */
10258		GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10259		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10260
10261		if (m_invalid_uniform_location == image_uniform_location)
10262		{
10263			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10264		}
10265
10266		/* Store results */
10267		out_program_details.m_depth_uniform_location = depth_uniform_location;
10268		out_program_details.m_image_uniform_location = image_uniform_location;
10269		out_program_details.m_program_id			 = program_id;
10270	}
10271
10272	/** Test if early fragment stencil test works as expected.
10273	 *
10274	 * @return true if successful, false otherwise
10275	 **/
10276	bool testEarlyStencil()
10277	{
10278		bool result = true;
10279
10280		glEnable(GL_STENCIL_TEST);
10281		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10282
10283		glClearDepthf(1.0f);
10284		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10285
10286		/* verify that early stencil test is applied when enabled */
10287		{
10288			glUseProgram(m_enabled_early_tests.m_program_id);
10289			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10290
10291			glClearStencil(0);
10292			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10293
10294			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10295			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10296
10297			cleanTexture();
10298
10299			glStencilFunc(GL_LESS, 128, 0xffffffff);
10300			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10301
10302			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10303			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10304
10305			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10306			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10307
10308			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10309			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10310
10311			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10312			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10313
10314			if (false == isTextureFilledWithValue(0.0f))
10315			{
10316				m_context.getTestContext().getLog() << tcu::TestLog::Message
10317													<< "Problem with early stencil test. It is not applied"
10318													<< tcu::TestLog::EndMessage;
10319
10320				result = false;
10321			}
10322		}
10323
10324		/* verify that early stencil test does not discard all fragments */
10325		{
10326			glClearStencil(128);
10327			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10328
10329			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10330			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10331
10332			cleanTexture();
10333
10334			glStencilFunc(GL_LESS, 0, 0xffffffff);
10335			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10336
10337			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10338			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10339
10340			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10341			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10342
10343			if (false == isTextureFilledWithValue(1.0f))
10344			{
10345				m_context.getTestContext().getLog()
10346					<< tcu::TestLog::Message
10347					<< "Problem with early stencil test. It discards fragments, that shall be drawn"
10348					<< tcu::TestLog::EndMessage;
10349
10350				result = false;
10351			}
10352		}
10353
10354		/* verify that early stencil test is not applied when disabled */
10355		{
10356			glUseProgram(m_disabled_early_tests.m_program_id);
10357			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10358
10359			glClearStencil(0);
10360			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10361
10362			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10363			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10364
10365			cleanTexture();
10366
10367			glStencilFunc(GL_LESS, 128, 0xffffffff);
10368			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10369
10370			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10371			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10372
10373			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10374			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10375
10376			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10377			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10378
10379			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10380			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10381
10382			if (false == isTextureFilledWithValue(1.0f))
10383			{
10384				m_context.getTestContext().getLog() << tcu::TestLog::Message
10385													<< "Problem with early stencil test. It is applied when disabled"
10386													<< tcu::TestLog::EndMessage;
10387
10388				result = false;
10389			}
10390		}
10391
10392		glDisable(GL_STENCIL_TEST);
10393		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10394
10395		/* Done */
10396		return result;
10397	}
10398
10399	/** Test if early fragment depth test works as expected.
10400	 *
10401	 * @return true if successful, false otherwise
10402	 **/
10403	bool testEarlyZ()
10404	{
10405		bool result = true;
10406
10407		glEnable(GL_DEPTH_TEST);
10408		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10409
10410		glClearDepthf(0.5f);
10411		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10412
10413		glClearStencil(0);
10414		GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10415
10416		/* verify that early z test is applied when enabled */
10417		{
10418			glUseProgram(m_enabled_early_tests.m_program_id);
10419			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10420
10421			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10422			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10423
10424			cleanTexture();
10425
10426			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10427			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10428
10429			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10430			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10431
10432			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10433			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10434
10435			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10436			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10437
10438			if (false == isTextureFilledWithValue(0.0f))
10439			{
10440				m_context.getTestContext().getLog() << tcu::TestLog::Message
10441													<< "Problem with early z test. It is not applied"
10442													<< tcu::TestLog::EndMessage;
10443
10444				result = false;
10445			}
10446		}
10447
10448		/* verify that early z test does not discard all fragments */
10449		{
10450			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10451			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10452
10453			cleanTexture();
10454
10455			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10456			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10457
10458			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10459			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10460
10461			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10462			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10463
10464			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10465			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10466
10467			if (false == isTextureFilledWithValue(1.0f))
10468			{
10469				m_context.getTestContext().getLog()
10470					<< tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10471					<< tcu::TestLog::EndMessage;
10472
10473				result = false;
10474			}
10475		}
10476
10477		/* verify that early z test is not applied when disabled */
10478		{
10479			glUseProgram(m_disabled_early_tests.m_program_id);
10480			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10481
10482			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10483			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10484
10485			cleanTexture();
10486
10487			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10488			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10489
10490			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10491			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10492
10493			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10494			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10495
10496			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10497			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10498
10499			if (false == isTextureFilledWithValue(1.0f))
10500			{
10501				m_context.getTestContext().getLog() << tcu::TestLog::Message
10502													<< "Problem with early z test. It is applied when disabled"
10503													<< tcu::TestLog::EndMessage;
10504
10505				result = false;
10506			}
10507		}
10508
10509		glDisable(GL_DEPTH_TEST);
10510		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10511
10512		/* Done */
10513		return result;
10514	}
10515};
10516
10517//-----------------------------------------------------------------------------
10518// 4.1 NegativeUniform
10519//-----------------------------------------------------------------------------
10520class NegativeUniform : public ShaderImageLoadStoreBase
10521{
10522	GLuint m_program;
10523
10524	virtual long Setup()
10525	{
10526		m_program = 0;
10527		return NO_ERROR;
10528	}
10529
10530	virtual long Run()
10531	{
10532		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10533							  "  gl_Position = i_position;" NL "}";
10534		const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10535							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10536							  "  discard;" NL "}";
10537		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10538
10539		GLint max_image_units;
10540		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10541		glUseProgram(m_program);
10542
10543		glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10544		if (glGetError() != GL_INVALID_VALUE)
10545		{
10546			m_context.getTestContext().getLog()
10547				<< tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10548				<< tcu::TestLog::EndMessage;
10549			return ERROR;
10550		}
10551		glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10552		if (glGetError() != GL_INVALID_VALUE)
10553		{
10554			m_context.getTestContext().getLog()
10555				<< tcu::TestLog::Message
10556				<< "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10557				<< "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10558			return ERROR;
10559		}
10560
10561		GLint i = -3;
10562		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10563		if (glGetError() != GL_INVALID_VALUE)
10564		{
10565			m_context.getTestContext().getLog()
10566				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10567				<< tcu::TestLog::EndMessage;
10568			return ERROR;
10569		}
10570		i = max_image_units + 1;
10571		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10572		if (glGetError() != GL_INVALID_VALUE)
10573		{
10574			m_context.getTestContext().getLog()
10575				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10576											"than or equal to the value of MAX_IMAGE_UNITS."
10577				<< tcu::TestLog::EndMessage;
10578			return ERROR;
10579		}
10580
10581		glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10582		if (glGetError() != GL_INVALID_OPERATION)
10583		{
10584			m_context.getTestContext().getLog()
10585				<< tcu::TestLog::Message
10586				<< "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10587				<< tcu::TestLog::EndMessage;
10588			return ERROR;
10589		}
10590		glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10591		if (glGetError() != GL_INVALID_OPERATION)
10592		{
10593			m_context.getTestContext().getLog()
10594				<< tcu::TestLog::Message
10595				<< "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10596				<< tcu::TestLog::EndMessage;
10597			return ERROR;
10598		}
10599
10600		{
10601			glUseProgram(0);
10602
10603			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10604			if (glGetError() != GL_INVALID_VALUE)
10605			{
10606				m_context.getTestContext().getLog()
10607					<< tcu::TestLog::Message
10608					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10609					<< tcu::TestLog::EndMessage;
10610				return ERROR;
10611			}
10612			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10613			if (glGetError() != GL_INVALID_VALUE)
10614			{
10615				m_context.getTestContext().getLog()
10616					<< tcu::TestLog::Message
10617					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10618					   "value of MAX_IMAGE_UNITS."
10619					<< tcu::TestLog::EndMessage;
10620				return ERROR;
10621			}
10622
10623			GLint ii = -3;
10624			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10625			if (glGetError() != GL_INVALID_VALUE)
10626			{
10627				m_context.getTestContext().getLog()
10628					<< tcu::TestLog::Message
10629					<< "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10630					<< tcu::TestLog::EndMessage;
10631				return ERROR;
10632			}
10633			ii = max_image_units + 1;
10634			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10635			if (glGetError() != GL_INVALID_VALUE)
10636			{
10637				m_context.getTestContext().getLog()
10638					<< tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10639												"is greater than or equal to the value of MAX_IMAGE_UNITS."
10640					<< tcu::TestLog::EndMessage;
10641				return ERROR;
10642			}
10643
10644			glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10645			if (glGetError() != GL_INVALID_OPERATION)
10646			{
10647				m_context.getTestContext().getLog()
10648					<< tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10649												"location refers to an image variable."
10650					<< tcu::TestLog::EndMessage;
10651				return ERROR;
10652			}
10653			glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10654			if (glGetError() != GL_INVALID_OPERATION)
10655			{
10656				m_context.getTestContext().getLog()
10657					<< tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10658												"location refers to an image variable."
10659					<< tcu::TestLog::EndMessage;
10660				return ERROR;
10661			}
10662		}
10663
10664		return NO_ERROR;
10665	}
10666
10667	virtual long Cleanup()
10668	{
10669		glUseProgram(0);
10670		glDeleteProgram(m_program);
10671		return NO_ERROR;
10672	}
10673};
10674//-----------------------------------------------------------------------------
10675// 4.2 NegativeBind
10676//-----------------------------------------------------------------------------
10677class NegativeBind : public ShaderImageLoadStoreBase
10678{
10679	virtual long Setup()
10680	{
10681		return NO_ERROR;
10682	}
10683
10684	virtual long Run()
10685	{
10686		glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10687		if (glGetError() != GL_INVALID_VALUE)
10688		{
10689			m_context.getTestContext().getLog()
10690				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10691											"greater than or equal to the value of MAX_IMAGE_UNITS."
10692				<< tcu::TestLog::EndMessage;
10693			return ERROR;
10694		}
10695
10696		glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10697		if (glGetError() != GL_INVALID_VALUE)
10698		{
10699			m_context.getTestContext().getLog()
10700				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10701											"the name of an existing texture object."
10702				<< tcu::TestLog::EndMessage;
10703			return ERROR;
10704		}
10705
10706		glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10707		if (glGetError() != GL_INVALID_VALUE)
10708		{
10709			m_context.getTestContext().getLog()
10710				<< tcu::TestLog::Message
10711				<< "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10712				<< tcu::TestLog::EndMessage;
10713			return ERROR;
10714		}
10715		return NO_ERROR;
10716	}
10717
10718	virtual long Cleanup()
10719	{
10720		return NO_ERROR;
10721	}
10722};
10723//-----------------------------------------------------------------------------
10724// 4.3 NegativeCompileErrors
10725//-----------------------------------------------------------------------------
10726class NegativeCompileErrors : public ShaderImageLoadStoreBase
10727{
10728	virtual long Run()
10729	{
10730		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10731					 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10732					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10733			return ERROR;
10734
10735		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10736					 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10737					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10738			return ERROR;
10739
10740		if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10741					 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10742					 "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10743			return ERROR;
10744
10745		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10746					 "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10747			return ERROR;
10748
10749		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10750					 "readonly uniform image2D g_image;" NL "void main() {" NL
10751					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10752			return ERROR;
10753
10754		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10755					 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10756			return ERROR;
10757
10758		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10759					 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10760			return ERROR;
10761
10762		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10763					 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10764					 "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10765			return ERROR;
10766
10767		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10768					 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10769					 "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10770			return ERROR;
10771
10772		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10773					 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10774					 "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10775			return ERROR;
10776
10777		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10778					 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10779					 "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10780			return ERROR;
10781
10782		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10783					 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10784					 "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10785					 "}"))
10786			return ERROR;
10787
10788		return NO_ERROR;
10789	}
10790
10791	bool Compile(const std::string& source)
10792	{
10793		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10794
10795		const char* const src = source.c_str();
10796		glShaderSource(sh, 1, &src, NULL);
10797		glCompileShader(sh);
10798
10799		GLchar log[1024];
10800		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10801		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10802											<< log << tcu::TestLog::EndMessage;
10803
10804		GLint status;
10805		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10806		glDeleteShader(sh);
10807
10808		if (status == GL_TRUE)
10809		{
10810			m_context.getTestContext().getLog()
10811				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10812			return false;
10813		}
10814
10815		return true;
10816	}
10817};
10818//-----------------------------------------------------------------------------
10819// 4.4 NegativeLinkErrors
10820//-----------------------------------------------------------------------------
10821class NegativeLinkErrors : public ShaderImageLoadStoreBase
10822{
10823	virtual long Run()
10824	{
10825		if (!SupportedInVS(1))
10826			return NOT_SUPPORTED;
10827
10828		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10829				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10830				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10831				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10832				  "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10833				  "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10834			return ERROR;
10835
10836		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10837				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10838				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10839				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10840				  "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10841				  "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10842			return ERROR;
10843
10844		return NO_ERROR;
10845	}
10846
10847	bool Link(const std::string& vs, const std::string& fs)
10848	{
10849		const GLuint p = glCreateProgram();
10850
10851		const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10852		glAttachShader(p, vsh);
10853		glDeleteShader(vsh);
10854		const char* const vssrc = vs.c_str();
10855		glShaderSource(vsh, 1, &vssrc, NULL);
10856		glCompileShader(vsh);
10857
10858		const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10859		glAttachShader(p, fsh);
10860		glDeleteShader(fsh);
10861		const char* const fssrc = fs.c_str();
10862		glShaderSource(fsh, 1, &fssrc, NULL);
10863		glCompileShader(fsh);
10864
10865		GLint status;
10866		glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10867		if (status == GL_FALSE)
10868		{
10869			glDeleteProgram(p);
10870			m_context.getTestContext().getLog()
10871				<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10872			return false;
10873		}
10874		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10875		if (status == GL_FALSE)
10876		{
10877			glDeleteProgram(p);
10878			m_context.getTestContext().getLog()
10879				<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10880			return false;
10881		}
10882
10883		glLinkProgram(p);
10884
10885		GLchar log[1024];
10886		glGetProgramInfoLog(p, sizeof(log), NULL, log);
10887		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10888											<< log << tcu::TestLog::EndMessage;
10889
10890		glGetProgramiv(p, GL_LINK_STATUS, &status);
10891		glDeleteProgram(p);
10892
10893		if (status == GL_TRUE)
10894		{
10895			m_context.getTestContext().getLog()
10896				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10897			return false;
10898		}
10899
10900		return true;
10901	}
10902};
10903
10904/** Negative Test "Active image uniform limits", description follows.
10905 *
10906 *  Program that exceeds resource limits should not compile and/or link.
10907 *
10908 *  Steps:
10909 *  - try to compile and link a program that uses too many image uniforms in
10910 *  fragment shader stage,
10911 *  - try to compile and link a program that uses too many image uniforms in
10912 *  vertex shader stage,
10913 *  - try to compile and link a program that uses too many image uniforms in
10914 *  tessellation control shader stage,
10915 *  - try to compile and link a program that uses too many image uniforms in
10916 *  tessellation evaluation shader stage,
10917 *  - try to compile and link a program that uses too many image uniforms in
10918 *  geometry shader stage,
10919 *  - try to compile and link a program that uses too many image uniforms in all
10920 *  shader stages combined, any single stage should not exceed its limits, this
10921 *  step might be impossible to fulfill.
10922 *
10923 *  Test should use the following declaration of image uniforms:
10924 *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
10925 *
10926 *  For cases where limit for single stage is tested, N_UNIFORMS should be
10927 *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
10928 *  corresponding to tested shader stage.
10929 *
10930 *  For case where limit for combined stages is tested:
10931 *  - u_image name should be appended with the name of shader stage, like
10932 *  u_image_vertex,
10933 *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
10934 *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
10935 *  - compilation and linking shall succeed, when sum of all
10936 *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
10937 *  gl_MaxCombinedImageUniforms.
10938 *
10939 *  All defined image uniforms have to be active. Each shader stage that declare
10940 *  image uniforms should include following code snippet:
10941 *  value = 1;
10942 *  for (int i = 0; i < N_UNIFORMS; ++i)
10943 *  {
10944 *      value = imageAtomicAdd(u_image[i], coord, value);
10945 *  }
10946 **/
10947class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
10948{
10949private:
10950	/* Fields */
10951	/* Results */
10952	bool m_result_for_combined;
10953	bool m_result_for_fragment_shader;
10954	bool m_result_for_geometry_shader;
10955	bool m_result_for_tesselation_control_shader;
10956	bool m_result_for_tesselatioon_evaluation_shader;
10957	bool m_result_for_vertex_shader;
10958
10959public:
10960	/* Constructor */
10961	ImageLoadStoreUniformLimitsTest()
10962		: m_result_for_combined(false)
10963		, m_result_for_fragment_shader(false)
10964		, m_result_for_geometry_shader(false)
10965		, m_result_for_tesselation_control_shader(false)
10966		, m_result_for_tesselatioon_evaluation_shader(false)
10967		, m_result_for_vertex_shader(false)
10968	{
10969		/* Nothing to be done */
10970	}
10971
10972	/* Methods inherited from SubcaseBase */
10973	virtual long Cleanup()
10974	{
10975		/* Done */
10976		return NO_ERROR;
10977	}
10978
10979	virtual long Run()
10980	{
10981		m_context.getTestContext().getLog() << tcu::TestLog::Message
10982											<< "This test tries to build invalid programs, expect error messages about "
10983											   "exceeded number of active image uniforms"
10984											<< tcu::TestLog::EndMessage;
10985
10986		testFragmentShaderStage();
10987		testGeometryShaderStage();
10988		testTesselationControlShaderStage();
10989		testTesselationEvaluationShaderStage();
10990		testVertexShaderStage();
10991		testCombinedShaderStages();
10992
10993		/* Return error if any stage failed */
10994		if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
10995			(false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
10996			(false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
10997		{
10998			return ERROR;
10999		}
11000
11001		/* Done */
11002		return NO_ERROR;
11003	}
11004
11005	virtual long Setup()
11006	{
11007		/* Done */
11008		return NO_ERROR;
11009	}
11010
11011private:
11012	/** Test fragment shader stage
11013	 *
11014	 **/
11015	void testFragmentShaderStage()
11016	{
11017		static const char* const fragment_shader_code =
11018			"#version 400 core\n"
11019			"#extension GL_ARB_shader_image_load_store : require\n"
11020			"\n"
11021			"precision highp float;\n"
11022			"\n"
11023			"#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11024			"\n"
11025			"flat in ivec2 vs_fs_coord;\n"
11026			"\n"
11027			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11028			"\n"
11029			"void main()\n"
11030			"{\n"
11031			"    int value = 1;\n"
11032			"\n"
11033			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11034			"    {\n"
11035			"        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11036			"    }\n"
11037			"\n"
11038			"    discard;\n"
11039			"}\n\n";
11040
11041		static const char* const vertex_shader_code = "#version 400 core\n"
11042													  "#extension GL_ARB_shader_image_load_store : require\n"
11043													  "\n"
11044													  "precision highp float;\n"
11045													  "\n"
11046													  "     in  ivec2 vs_in_coord;\n"
11047													  "flat out ivec2 vs_fs_coord;\n"
11048													  "\n"
11049													  "void main()\n"
11050													  "{\n"
11051													  "    vs_fs_coord = vs_in_coord;\n"
11052													  "}\n\n";
11053
11054		m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11055														0 /* tesselation_control_shader_code */,
11056														0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11057
11058		if (false == m_result_for_fragment_shader)
11059		{
11060			m_context.getTestContext().getLog()
11061				<< tcu::TestLog::Message
11062				<< "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11063				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11064				<< fragment_shader_code << tcu::TestLog::EndMessage;
11065		}
11066	}
11067
11068	/** Test geometry shader stage
11069	 *
11070	 **/
11071	void testGeometryShaderStage()
11072	{
11073		static const char* const fragment_shader_code = "#version 400 core\n"
11074														"#extension GL_ARB_shader_image_load_store : require\n"
11075														"\n"
11076														"precision highp float;\n"
11077														"\n"
11078														"void main()\n"
11079														"{\n"
11080														"    discard;\n"
11081														"}\n\n";
11082
11083		static const char* const geometry_shader_code =
11084			"#version 400 core\n"
11085			"#extension GL_ARB_shader_image_load_store : require\n"
11086			"\n"
11087			"precision highp float;\n"
11088			"\n"
11089			"layout(points)                   in;\n"
11090			"layout(points, max_vertices = 1) out;\n"
11091			"\n"
11092			"#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11093			"\n"
11094			"in ivec2 vs_gs_coord[];\n"
11095			"\n"
11096			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11097			"\n"
11098			"void main()\n"
11099			"{\n"
11100			"    int value = 1;\n"
11101			"\n"
11102			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11103			"    {\n"
11104			"        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11105			"    }\n"
11106			"}\n\n";
11107
11108		static const char* const vertex_shader_code = "#version 400 core\n"
11109													  "#extension GL_ARB_shader_image_load_store : require\n"
11110													  "\n"
11111													  "precision highp float;\n"
11112													  "\n"
11113													  "in  ivec2 vs_in_coord;\n"
11114													  "out ivec2 vs_gs_coord;\n"
11115													  "\n"
11116													  "void main()\n"
11117													  "{\n"
11118													  "    vs_gs_coord = vs_in_coord;\n"
11119													  "}\n\n";
11120
11121		m_result_for_geometry_shader =
11122			!doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11123							 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11124
11125		if (false == m_result_for_geometry_shader)
11126		{
11127			m_context.getTestContext().getLog()
11128				<< tcu::TestLog::Message
11129				<< "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11130				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11131				<< geometry_shader_code << tcu::TestLog::EndMessage;
11132		}
11133	}
11134
11135	/** Test tesselation control shader stage
11136	 *
11137	 **/
11138	void testTesselationControlShaderStage()
11139	{
11140		static const char* const fragment_shader_code = "#version 400 core\n"
11141														"#extension GL_ARB_shader_image_load_store : require\n"
11142														"\n"
11143														"precision highp float;\n"
11144														"\n"
11145														"void main()\n"
11146														"{\n"
11147														"    discard;\n"
11148														"}\n\n";
11149
11150		static const char* const tesselation_control_shader_code =
11151			"#version 400 core\n"
11152			"#extension GL_ARB_shader_image_load_store : require\n"
11153			"\n"
11154			"precision highp float;\n"
11155			"\n"
11156			"layout(vertices = 4) out;\n"
11157			"\n"
11158			"#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11159			"\n"
11160			"in ivec2 vs_tcs_coord[];\n"
11161			"\n"
11162			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11163			"\n"
11164			"void main()\n"
11165			"{\n"
11166			"    int value = 1;\n"
11167			"\n"
11168			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11169			"    {\n"
11170			"        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11171			"    }\n"
11172			"}\n\n";
11173
11174		static const char* const tesselation_evaluation_shader_code =
11175			"#version 400 core\n"
11176			"#extension GL_ARB_shader_image_load_store : require\n"
11177			"\n"
11178			"precision highp float;\n"
11179			"\n"
11180			"layout(quads, equal_spacing, ccw) in;\n"
11181			"\n"
11182			"void main()\n"
11183			"{\n"
11184			"}\n";
11185
11186		static const char* const vertex_shader_code = "#version 400 core\n"
11187													  "#extension GL_ARB_shader_image_load_store : require\n"
11188													  "\n"
11189													  "precision highp float;\n"
11190													  "\n"
11191													  "in  ivec2 vs_in_coord;\n"
11192													  "out ivec2 vs_tcs_coord;\n"
11193													  "\n"
11194													  "void main()\n"
11195													  "{\n"
11196													  "    vs_tcs_coord = vs_in_coord;\n"
11197													  "}\n\n";
11198
11199		m_result_for_tesselation_control_shader =
11200			!doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11201							 tesselation_evaluation_shader_code, vertex_shader_code);
11202
11203		if (false == m_result_for_tesselation_control_shader)
11204		{
11205			m_context.getTestContext().getLog()
11206				<< tcu::TestLog::Message
11207				<< "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11208				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11209				<< tesselation_control_shader_code << tcu::TestLog::EndMessage;
11210		}
11211	}
11212
11213	/** Test teselation evaluation shader stage
11214	 *
11215	 **/
11216	void testTesselationEvaluationShaderStage()
11217	{
11218		static const char* const fragment_shader_code = "#version 400 core\n"
11219														"#extension GL_ARB_shader_image_load_store : require\n"
11220														"\n"
11221														"precision highp float;\n"
11222														"\n"
11223														"void main()\n"
11224														"{\n"
11225														"    discard;\n"
11226														"}\n\n";
11227
11228		static const char* const tesselation_evaluation_shader_code =
11229			"#version 400 core\n"
11230			"#extension GL_ARB_shader_image_load_store : require\n"
11231			"\n"
11232			"precision highp float;\n"
11233			"\n"
11234			"layout(quads, equal_spacing, ccw) in;\n"
11235			"\n"
11236			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11237			"\n"
11238			"in ivec2 vs_tes_coord[];\n"
11239			"\n"
11240			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11241			"\n"
11242			"void main()\n"
11243			"{\n"
11244			"    int value = 1;\n"
11245			"\n"
11246			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11247			"    {\n"
11248			"        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11249			"    }\n"
11250			"}\n\n";
11251
11252		static const char* const vertex_shader_code = "#version 400 core\n"
11253													  "#extension GL_ARB_shader_image_load_store : require\n"
11254													  "\n"
11255													  "precision highp float;\n"
11256													  "\n"
11257													  "in  ivec2 vs_in_coord;\n"
11258													  "out ivec2 vs_tes_coord;\n"
11259													  "\n"
11260													  "void main()\n"
11261													  "{\n"
11262													  "    vs_tes_coord = vs_in_coord;\n"
11263													  "}\n\n";
11264
11265		m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11266			fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11267			tesselation_evaluation_shader_code, vertex_shader_code);
11268
11269		if (false == m_result_for_tesselatioon_evaluation_shader)
11270		{
11271			m_context.getTestContext().getLog()
11272				<< tcu::TestLog::Message
11273				<< "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11274				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11275				<< tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11276		}
11277	}
11278
11279	/** Test vertex shader stage
11280	 *
11281	 **/
11282	void testVertexShaderStage()
11283	{
11284		static const char* const fragment_shader_code = "#version 400 core\n"
11285														"#extension GL_ARB_shader_image_load_store : require\n"
11286														"\n"
11287														"precision highp float;\n"
11288														"\n"
11289														"void main()\n"
11290														"{\n"
11291														"    discard;\n"
11292														"}\n\n";
11293
11294		static const char* const vertex_shader_code =
11295			"#version 400 core\n"
11296			"#extension GL_ARB_shader_image_load_store : require\n"
11297			"\n"
11298			"precision highp float;\n"
11299			"\n"
11300			"in ivec2 vs_in_coord;\n"
11301			"\n"
11302			"#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11303			"\n"
11304			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11305			"\n"
11306			"void main()\n"
11307			"{\n"
11308			"    int value = 1;\n"
11309			"\n"
11310			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11311			"    {\n"
11312			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11313			"    }\n"
11314			"}\n\n";
11315
11316		m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11317													  0 /* tesselation_control_shader_code */,
11318													  0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11319
11320		if (false == m_result_for_vertex_shader)
11321		{
11322			m_context.getTestContext().getLog()
11323				<< tcu::TestLog::Message
11324				<< "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11325				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11326				<< vertex_shader_code << tcu::TestLog::EndMessage;
11327		}
11328	}
11329
11330	/** Test combined shader stages
11331	 *
11332	 **/
11333	void testCombinedShaderStages()
11334	{
11335		static const char* const fragment_shader_code =
11336			"#version 400 core\n"
11337			"#extension GL_ARB_shader_image_load_store : require\n"
11338			"\n"
11339			"precision highp float;\n"
11340			"\n"
11341			"#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11342			"\n"
11343			"flat in ivec2 gs_fs_coord;\n"
11344			"\n"
11345			"layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11346			"\n"
11347			"void main()\n"
11348			"{\n"
11349			"    int value = 1;\n"
11350			"\n"
11351			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11352			"    {\n"
11353			"        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11354			"    }\n"
11355			"\n"
11356			"    discard;\n"
11357			"}\n\n";
11358
11359		static const char* const geometry_shader_code =
11360			"#version 400 core\n"
11361			"#extension GL_ARB_shader_image_load_store : require\n"
11362			"\n"
11363			"precision highp float;\n"
11364			"\n"
11365			"layout(points)                   in;\n"
11366			"layout(points, max_vertices = 1) out;\n"
11367			"\n"
11368			"#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11369			"\n"
11370			"flat in  ivec2 tes_gs_coord[];\n"
11371			"flat out ivec2 gs_fs_coord;\n"
11372			"\n"
11373			"layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11374			"\n"
11375			"void main()\n"
11376			"{\n"
11377			"    int value = 1;\n"
11378			"\n"
11379			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11380			"    {\n"
11381			"        value = imageAtomicAdd(u_image_geometry[i], tes_gs_coord[0], value);\n"
11382			"    }\n"
11383			"\n"
11384			"    gs_fs_coord = tes_gs_coord[0];\n"
11385			"    EmitVertex();\n"
11386			"}\n\n";
11387
11388		static const char* const tesselation_control_shader_code =
11389			"#version 400 core\n"
11390			"#extension GL_ARB_shader_image_load_store : require\n"
11391			"\n"
11392			"precision highp float;\n"
11393			"\n"
11394			"layout(vertices = 4) out;\n"
11395			"\n"
11396			"#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11397			"\n"
11398			"flat in  ivec2 vs_tcs_coord[];\n"
11399			"flat out ivec2 tcs_tes_coord[];\n"
11400			"\n"
11401			"layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11402			"\n"
11403			"void main()\n"
11404			"{\n"
11405			"    int value = 1;\n"
11406			"\n"
11407			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11408			"    {\n"
11409			"        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11410			"    }\n"
11411			"\n"
11412			"    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11413			"}\n\n";
11414
11415		static const char* const tesselation_evaluation_shader_code =
11416			"#version 400 core\n"
11417			"#extension GL_ARB_shader_image_load_store : require\n"
11418			"\n"
11419			"precision highp float;\n"
11420			"\n"
11421			"layout(quads, equal_spacing, ccw) in;\n"
11422			"\n"
11423			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11424			"\n"
11425			"flat in  ivec2 tcs_tes_coord[];\n"
11426			"flat out ivec2 tes_gs_coord;\n"
11427			"\n"
11428			"layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11429			"\n"
11430			"void main()\n"
11431			"{\n"
11432			"    int value = 1;\n"
11433			"\n"
11434			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11435			"    {\n"
11436			"        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11437			"    }\n"
11438			"\n"
11439			"    tes_gs_coord = tcs_tes_coord[0];\n"
11440			"}\n\n";
11441
11442		static const char* const vertex_shader_code =
11443			"#version 400 core\n"
11444			"#extension GL_ARB_shader_image_load_store : require\n"
11445			"\n"
11446			"precision highp float;\n"
11447			"\n"
11448			"     in  ivec2 vs_in_coord;\n"
11449			"flat out ivec2 vs_tcs_coord;\n"
11450			"\n"
11451			"#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11452			"\n"
11453			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11454			"\n"
11455			"void main()\n"
11456			"{\n"
11457			"    int value = 1;\n"
11458			"\n"
11459			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11460			"    {\n"
11461			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11462			"    }\n"
11463			"\n"
11464			"    vs_tcs_coord = vs_tcs_coord;\n"
11465			"}\n\n";
11466
11467		/* Active image uniform limits */
11468		GLint max_combined_image_uniforms				= 0;
11469		GLint max_fragment_image_uniforms				= 0;
11470		GLint max_geometry_image_uniforms				= 0;
11471		GLint max_tesselation_control_image_uniforms	= 0;
11472		GLint max_tesselation_evaluation_image_uniforms = 0;
11473		GLint max_vertex_image_uniforms					= 0;
11474
11475		/* Get limit values */
11476		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11477		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11478		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11479		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11480		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11481		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11482		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11483
11484		/* Check if program builds */
11485		m_result_for_combined =
11486			!doesProgramLink(fragment_shader_code, geometry_shader_code, tesselation_control_shader_code,
11487							 tesselation_evaluation_shader_code, vertex_shader_code);
11488
11489		/* Result depends on the limit values */
11490		if (max_combined_image_uniforms >=
11491			(max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11492			 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11493		{
11494			/* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11495			m_result_for_combined = !m_result_for_combined;
11496
11497			if (false == m_result_for_combined)
11498			{
11499				m_context.getTestContext().getLog()
11500					<< tcu::TestLog::Message << "There was an error while building a program."
11501					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11502					<< vertex_shader_code << "\nTesselation control shader code:\n"
11503					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11504					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11505					<< geometry_shader_code << "\nFragment shader code:\n"
11506					<< fragment_shader_code << tcu::TestLog::EndMessage;
11507			}
11508		}
11509		else
11510		{
11511			/* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11512			if (false == m_result_for_combined)
11513			{
11514				m_context.getTestContext().getLog()
11515					<< tcu::TestLog::Message
11516					<< "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11517					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11518					<< vertex_shader_code << "\nTesselation control shader code:\n"
11519					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11520					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11521					<< geometry_shader_code << "\nFragment shader code:\n"
11522					<< fragment_shader_code << tcu::TestLog::EndMessage;
11523			}
11524		}
11525	}
11526
11527	/** Check if program builds successfully
11528	 *
11529	 * @param fragment_shader_code               Source code for fragment shader stage
11530	 * @param geometry_shader_code               Source code for geometry shader stage
11531	 * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11532	 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11533	 * @param vertex_shader_code                 Source code for vertex shader stage
11534	 *
11535	 * @return true if program was built without errors, false otherwise
11536	 **/
11537	bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11538						 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11539						 const char* vertex_shader_code)
11540	{
11541		bool   is_program_built = true;
11542		GLuint program_id		= 0;
11543
11544		program_id =
11545			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11546						 geometry_shader_code, fragment_shader_code, &is_program_built);
11547
11548		if (0 != program_id)
11549		{
11550			glDeleteProgram(program_id);
11551		}
11552
11553		return is_program_built;
11554	}
11555};
11556}
11557
11558ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11559	: TestCaseGroup(context, "shader_image_load_store", "")
11560{
11561}
11562
11563ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11564{
11565}
11566
11567void ShaderImageLoadStoreTests::init()
11568{
11569	using namespace deqp;
11570	addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11571	addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11572	addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11573	addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11574	addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11575	addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11576	addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11577							 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11578	addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11579							 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11580	addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11581							 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11582	addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11583	addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11584	addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11585	addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11586	addChild(
11587		new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11588	addChild(
11589		new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11590	addChild(
11591		new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11592	addChild(
11593		new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11594	addChild(
11595		new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11596	addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11597	addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11598	addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11599	addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11600	addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11601	addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11602	addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11603	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11604	addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11605	addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11606	addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11607	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11608	addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11609	addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11610	addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11611							 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11612	addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11613	addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11614	addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11615	addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11616	addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11617	addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11618	addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11619	addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11620	addChild(
11621		new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11622	addChild(
11623		new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11624	addChild(
11625		new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11626	addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11627	addChild(
11628		new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11629	addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11630	addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11631	addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11632	addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11633	addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11634}
11635}
11636