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 "tcuPlatform.hpp"
29#include "tcuRenderTarget.hpp"
30#include "tcuVectorUtil.hpp"
31#include <assert.h>
32#include <climits>
33#include <cmath>
34#include <cstdarg>
35#include <deque>
36#include <iomanip>
37#include <map>
38#include <sstream>
39#include <tcuFloat.hpp>
40
41namespace gl4cts
42{
43using namespace glw;
44
45namespace
46{
47typedef tcu::Vec2  vec2;
48typedef tcu::Vec4  vec4;
49typedef tcu::IVec4 ivec4;
50typedef tcu::UVec4 uvec4;
51typedef tcu::Mat4  mat4;
52
53class ShaderImageLoadStoreBase : public deqp::SubcaseBase
54{
55	virtual std::string Title()
56	{
57		return "";
58	}
59
60	virtual std::string Purpose()
61	{
62		return "";
63	}
64
65	virtual std::string Method()
66	{
67		return "";
68	}
69
70	virtual std::string PassCriteria()
71	{
72		return "";
73	}
74
75public:
76	bool SupportedInVS(int requiredVS)
77	{
78		GLint imagesVS;
79		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
80		if (imagesVS >= requiredVS)
81			return true;
82		else
83		{
84			std::ostringstream reason;
85			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
86				   << std::endl;
87			OutputNotSupported(reason.str());
88			return false;
89		}
90	}
91
92	bool SupportedInTCS(int requiredTCS)
93	{
94		GLint imagesTCS;
95		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
96		if (imagesTCS >= requiredTCS)
97			return true;
98		else
99		{
100			std::ostringstream reason;
101			reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
102				   << std::endl;
103			OutputNotSupported(reason.str());
104			return false;
105		}
106	}
107
108	bool SupportedInTES(int requiredTES)
109	{
110		GLint imagesTES;
111		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
112		if (imagesTES >= requiredTES)
113			return true;
114		else
115		{
116			std::ostringstream reason;
117			reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
118				   << std::endl;
119			OutputNotSupported(reason.str());
120			return false;
121		}
122	}
123
124	bool SupportedInGS(int requiredGS)
125	{
126		GLint imagesGS;
127		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
128		if (imagesGS >= requiredGS)
129			return true;
130		else
131		{
132			std::ostringstream reason;
133			reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
134				   << std::endl;
135			OutputNotSupported(reason.str());
136			return false;
137		}
138	}
139
140	bool SupportedInGeomStages(int required)
141	{
142		return SupportedInVS(required) && SupportedInTCS(required) && SupportedInTES(required) &&
143			   SupportedInGS(required);
144	}
145
146	bool SupportedInStage(int stage, int required)
147	{
148		switch (stage)
149		{
150		case 0:
151			return SupportedInVS(required);
152		case 1:
153			return SupportedInTCS(required);
154		case 2:
155			return SupportedInTES(required);
156		case 3:
157			return SupportedInGS(required);
158		default:
159			return true;
160		}
161	}
162
163	bool SupportedSamples(int required)
164	{
165		int i;
166		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
167		if (i >= required)
168			return true;
169		else
170		{
171			std::ostringstream reason;
172			reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
173			OutputNotSupported(reason.str());
174			return false;
175		}
176	}
177
178	int getWindowWidth()
179	{
180		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
181		return renderTarget.getWidth();
182	}
183
184	int getWindowHeight()
185	{
186		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
187		return renderTarget.getHeight();
188	}
189
190	void scaleDimensionsToMemory(int& width, int& height, int devLayers, int sysLayers, int devBPP, int sysBPP)
191	{
192		tcu::PlatformMemoryLimits memoryLimits;
193		m_context.getTestContext().getPlatform().getMemoryLimits(memoryLimits);
194		GLsizeiptr sysSpace		  = memoryLimits.totalSystemMemory;
195		GLsizeiptr devSpace		  = memoryLimits.totalDeviceLocalMemory;
196		int		   devInSysLayers = 0;
197
198		if (devSpace == 0)
199		{
200			devInSysLayers = devLayers;
201			devLayers	  = 0;
202		}
203
204		// Check if available memory is enough
205		GLsizeiptr pixelsPerLayer = width * height;
206		GLsizeiptr sysRequired	= pixelsPerLayer * ((sysBPP * sysLayers) + (devBPP * devInSysLayers));
207		GLsizeiptr devRequired	= pixelsPerLayer * devBPP * devLayers;
208		if ((sysRequired <= sysSpace) && (devRequired <= devSpace))
209		{
210			return;
211		}
212
213		// Scales the width and height such that the overall texture fits into
214		// the available space for both system and device.
215		GLdouble scale = sqrt(sysSpace / GLdouble(sysRequired));
216		if (devSpace != 0)
217		{
218			GLdouble devScale = sqrt(devSpace / GLdouble(devRequired));
219			scale			  = de::min(devScale, scale);
220		}
221		int newWidth  = int(width * scale);
222		int newHeight = int(height * scale);
223
224		m_context.getTestContext().getLog()
225			<< tcu::TestLog::Message << "Reducing surface dimensions to fit in memory, from " << width << "x" << height
226			<< " to " << newWidth << "x" << newHeight << "." << tcu::TestLog::EndMessage;
227
228		width  = newWidth;
229		height = newHeight;
230	}
231
232	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
233	{
234		if (fabs(c0[0] - c1[0]) > epsilon[0])
235			return false;
236		if (fabs(c0[1] - c1[1]) > epsilon[1])
237			return false;
238		if (fabs(c0[2] - c1[2]) > epsilon[2])
239			return false;
240		if (fabs(c0[3] - c1[3]) > epsilon[3])
241			return false;
242		return true;
243	}
244
245	bool IsEqual(vec4 a, vec4 b)
246	{
247		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
248	}
249
250	bool Equal(const vec4& v0, const vec4& v1, GLenum internalformat)
251	{
252		if (internalformat == GL_RGBA16_SNORM || internalformat == GL_RG16_SNORM || internalformat == GL_R16_SNORM)
253		{
254			return ColorEqual(v0, v1, vec4(0.0001f));
255		}
256		else if (internalformat == GL_RGBA8_SNORM || internalformat == GL_RG8_SNORM || internalformat == GL_R8_SNORM)
257		{
258			return ColorEqual(v0, v1, vec4(0.01f));
259		}
260		return (v0[0] == v1[0]) && (v0[1] == v1[1]) && (v0[2] == v1[2]) && (v0[3] == v1[3]);
261	}
262
263	bool Equal(const ivec4& a, const ivec4& b, GLenum)
264	{
265		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
266	}
267
268	bool Equal(const uvec4& a, const uvec4& b, GLenum)
269	{
270		return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
271	}
272
273	template <class T>
274	std::string ToString(T v)
275	{
276		std::ostringstream s;
277		s << "[";
278		for (int i = 0; i < 4; ++i)
279			s << v[i] << (i == 3 ? "" : ",");
280		s << "]";
281		return s.str();
282	}
283
284	bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
285	{
286		bool					 status		  = true;
287		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
288		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
289		vec4					 g_color_eps  = vec4(
290			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
291			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
292
293		std::vector<vec4> fb(w * h);
294		glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
295
296		for (int yy = 0; yy < h; ++yy)
297		{
298			for (int xx = 0; xx < w; ++xx)
299			{
300				const int idx = yy * w + xx;
301				if (!ColorEqual(fb[idx], expected, g_color_eps))
302				{
303					m_context.getTestContext().getLog()
304						<< tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
305						<< tcu::TestLog::EndMessage;
306					status = false;
307					return status;
308				}
309			}
310		}
311		return status;
312	}
313
314	bool CompileShader(GLuint shader)
315	{
316		glCompileShader(shader);
317
318		GLint status;
319		glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
320		if (status == GL_FALSE)
321		{
322			GLsizei length;
323			GLchar  log[1024];
324			glGetShaderInfoLog(shader, sizeof(log), &length, log);
325			if (length > 1)
326			{
327				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
328													<< log << tcu::TestLog::EndMessage;
329			}
330			return false;
331		}
332		return true;
333	}
334
335	bool LinkProgram(GLuint program)
336	{
337		glLinkProgram(program);
338
339		GLint status;
340		glGetProgramiv(program, GL_LINK_STATUS, &status);
341		if (status == GL_FALSE)
342		{
343			GLsizei length;
344			GLchar  log[1024];
345			glGetProgramInfoLog(program, sizeof(log), &length, log);
346			if (length > 1)
347			{
348				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
349													<< log << tcu::TestLog::EndMessage;
350			}
351			return false;
352		}
353		return true;
354	}
355
356	GLuint BuildProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
357						const char* src_fs, bool* result = NULL)
358	{
359		const GLuint p = glCreateProgram();
360
361		if (src_vs)
362		{
363			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
364			glAttachShader(p, sh);
365			glDeleteShader(sh);
366			glShaderSource(sh, 1, &src_vs, NULL);
367			if (!CompileShader(sh))
368			{
369				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
370				if (result)
371					*result = false;
372				return p;
373			}
374		}
375		if (src_tcs)
376		{
377			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
378			glAttachShader(p, sh);
379			glDeleteShader(sh);
380			glShaderSource(sh, 1, &src_tcs, NULL);
381			if (!CompileShader(sh))
382			{
383				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
384				if (result)
385					*result = false;
386				return p;
387			}
388		}
389		if (src_tes)
390		{
391			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
392			glAttachShader(p, sh);
393			glDeleteShader(sh);
394			glShaderSource(sh, 1, &src_tes, NULL);
395			if (!CompileShader(sh))
396			{
397				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
398				if (result)
399					*result = false;
400				return p;
401			}
402		}
403		if (src_gs)
404		{
405			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
406			glAttachShader(p, sh);
407			glDeleteShader(sh);
408			glShaderSource(sh, 1, &src_gs, NULL);
409			if (!CompileShader(sh))
410			{
411				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
412				if (result)
413					*result = false;
414				return p;
415			}
416		}
417		if (src_fs)
418		{
419			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
420			glAttachShader(p, sh);
421			glDeleteShader(sh);
422			glShaderSource(sh, 1, &src_fs, NULL);
423			if (!CompileShader(sh))
424			{
425				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
426				if (result)
427					*result = false;
428				return p;
429			}
430		}
431		if (!LinkProgram(p))
432		{
433			if (src_vs)
434				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_vs << tcu::TestLog::EndMessage;
435			if (src_tcs)
436				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tcs << tcu::TestLog::EndMessage;
437			if (src_tes)
438				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_tes << tcu::TestLog::EndMessage;
439			if (src_gs)
440				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_gs << tcu::TestLog::EndMessage;
441			if (src_fs)
442				m_context.getTestContext().getLog() << tcu::TestLog::Message << src_fs << tcu::TestLog::EndMessage;
443			if (result)
444				*result = false;
445			return p;
446		}
447
448		return p;
449	}
450
451	GLuint BuildShaderProgram(GLenum type, const char* src)
452	{
453		const GLuint p = glCreateShaderProgramv(type, 1, &src);
454
455		GLint status;
456		glGetProgramiv(p, GL_LINK_STATUS, &status);
457		if (status == GL_FALSE)
458		{
459			GLchar log[1024];
460			glGetProgramInfoLog(p, sizeof(log), NULL, log);
461			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
462												<< log << "\n"
463												<< src << tcu::TestLog::EndMessage;
464		}
465
466		return p;
467	}
468
469	void CreateFullViewportQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
470	{
471		assert(vao && vbo);
472
473		// interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
474		const float v[] = {
475			-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,
476			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,
477			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,
478		};
479		glGenBuffers(1, vbo);
480		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
481		glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
482		glBindBuffer(GL_ARRAY_BUFFER, 0);
483
484		if (ebo)
485		{
486			std::vector<GLushort> index_data(4);
487			for (int i = 0; i < 4; ++i)
488			{
489				index_data[i] = static_cast<GLushort>(i);
490			}
491			glGenBuffers(1, ebo);
492			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
493			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
494			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
495		}
496
497		glGenVertexArrays(1, vao);
498		glBindVertexArray(*vao);
499		glBindBuffer(GL_ARRAY_BUFFER, *vbo);
500		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
501		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
502		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
503		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
504		glBindBuffer(GL_ARRAY_BUFFER, 0);
505		glEnableVertexAttribArray(0);
506		glEnableVertexAttribArray(1);
507		glEnableVertexAttribArray(2);
508		glEnableVertexAttribArray(3);
509		if (ebo)
510		{
511			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
512		}
513		glBindVertexArray(0);
514	}
515
516	std::string FormatEnumToString(GLenum e)
517	{
518		switch (e)
519		{
520		case GL_RGBA32F:
521			return "rgba32f";
522		case GL_RGBA16F:
523			return "rgba16f";
524		case GL_RG32F:
525			return "rg32f";
526		case GL_RG16F:
527			return "rg16f";
528		case GL_R11F_G11F_B10F:
529			return "r11f_g11f_b10f";
530		case GL_R32F:
531			return "r32f";
532		case GL_R16F:
533			return "r16f";
534
535		case GL_RGBA32UI:
536			return "rgba32ui";
537		case GL_RGBA16UI:
538			return "rgba16ui";
539		case GL_RGB10_A2UI:
540			return "rgb10_a2ui";
541		case GL_RGBA8UI:
542			return "rgba8ui";
543		case GL_RG32UI:
544			return "rg32ui";
545		case GL_RG16UI:
546			return "rg16ui";
547		case GL_RG8UI:
548			return "rg8ui";
549		case GL_R32UI:
550			return "r32ui";
551		case GL_R16UI:
552			return "r16ui";
553		case GL_R8UI:
554			return "r8ui";
555
556		case GL_RGBA32I:
557			return "rgba32i";
558		case GL_RGBA16I:
559			return "rgba16i";
560		case GL_RGBA8I:
561			return "rgba8i";
562		case GL_RG32I:
563			return "rg32i";
564		case GL_RG16I:
565			return "rg16i";
566		case GL_RG8I:
567			return "rg8i";
568		case GL_R32I:
569			return "r32i";
570		case GL_R16I:
571			return "r16i";
572		case GL_R8I:
573			return "r8i";
574
575		case GL_RGBA16:
576			return "rgba16";
577		case GL_RGB10_A2:
578			return "rgb10_a2";
579		case GL_RGBA8:
580			return "rgba8";
581		case GL_RG16:
582			return "rg16";
583		case GL_RG8:
584			return "rg8";
585		case GL_R16:
586			return "r16";
587		case GL_R8:
588			return "r8";
589
590		case GL_RGBA16_SNORM:
591			return "rgba16_snorm";
592		case GL_RGBA8_SNORM:
593			return "rgba8_snorm";
594		case GL_RG16_SNORM:
595			return "rg16_snorm";
596		case GL_RG8_SNORM:
597			return "rg8_snorm";
598		case GL_R16_SNORM:
599			return "r16_snorm";
600		case GL_R8_SNORM:
601			return "r8_snorm";
602		}
603
604		assert(0);
605		return "";
606	}
607
608	const char* StageName(int stage)
609	{
610		switch (stage)
611		{
612		case 0:
613			return "Vertex Shader";
614		case 1:
615			return "Tessellation Control Shader";
616		case 2:
617			return "Tessellation Evaluation Shader";
618		case 3:
619			return "Geometry Shader";
620		case 4:
621			return "Compute Shader";
622		}
623		assert(0);
624		return NULL;
625	}
626
627	template <typename T>
628	GLenum Format();
629
630	template <typename T>
631	GLenum Type();
632
633	template <typename T>
634	std::string TypePrefix();
635
636	template <typename T>
637	GLenum ImageType(GLenum target);
638
639	void ClearBuffer(GLenum buffer, GLint drawbuffer, const vec4& color)
640	{
641		glClearBufferfv(buffer, drawbuffer, &color[0]);
642	}
643
644	void ClearBuffer(GLenum buffer, GLint drawbuffer, const ivec4& color)
645	{
646		glClearBufferiv(buffer, drawbuffer, &color[0]);
647	}
648
649	void ClearBuffer(GLenum buffer, GLint drawbuffer, const uvec4& color)
650	{
651		glClearBufferuiv(buffer, drawbuffer, &color[0]);
652	}
653
654	bool CheckUniform(GLuint program, const std::string& name, const std::map<std::string, GLuint>& name_index_map,
655					  GLint size, GLenum type)
656	{
657		std::map<std::string, GLuint>::const_iterator iter = name_index_map.find(name);
658		assert(iter != name_index_map.end());
659
660		GLchar  name_gl[32];
661		GLsizei length_gl;
662		GLint   size_gl;
663		GLenum  type_gl;
664
665		glGetActiveUniform(program, iter->second, sizeof(name_gl), &length_gl, &size_gl, &type_gl, name_gl);
666
667		if (std::string(name_gl) != name)
668		{
669			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform name is " << name_gl
670												<< " should be " << name << tcu::TestLog::EndMessage;
671			return false;
672		}
673		if (length_gl != static_cast<GLsizei>(name.length()))
674		{
675			m_context.getTestContext().getLog()
676				<< tcu::TestLog::Message << "Uniform length is " << length_gl << " should be " << name << "(" << name_gl
677				<< ")" << tcu::TestLog::EndMessage;
678			return false;
679		}
680		if (size_gl != size)
681		{
682			m_context.getTestContext().getLog()
683				<< tcu::TestLog::Message << "Uniform size is " << size_gl << " should be " << size << "(" << name_gl
684				<< ")" << tcu::TestLog::EndMessage;
685			return false;
686		}
687		if (type_gl != type)
688		{
689			m_context.getTestContext().getLog()
690				<< tcu::TestLog::Message << "Uniform type is " << type_gl << " should be " << type << "(" << name_gl
691				<< ")" << tcu::TestLog::EndMessage;
692			return false;
693		}
694
695		return true;
696	}
697
698	bool CheckMax(GLenum pname, GLint min_value)
699	{
700		GLboolean b;
701		GLint	 i;
702		GLfloat   f;
703		GLdouble  d;
704		GLint64   i64;
705
706		glGetIntegerv(pname, &i);
707		if (i < min_value)
708			return false;
709
710		glGetBooleanv(pname, &b);
711		if (b != (i ? GL_TRUE : GL_FALSE))
712			return false;
713
714		glGetFloatv(pname, &f);
715		if (static_cast<GLint>(f) < min_value)
716			return false;
717
718		glGetDoublev(pname, &d);
719		if (static_cast<GLint>(d) < min_value)
720			return false;
721
722		glGetInteger64v(pname, &i64);
723		if (static_cast<GLint>(i64) < min_value)
724			return false;
725
726		return true;
727	}
728
729	bool CheckBinding(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access,
730					  GLenum format)
731	{
732		GLint	 i;
733		GLboolean b;
734
735		glGetIntegeri_v(GL_IMAGE_BINDING_NAME, unit, &i);
736		if (static_cast<GLuint>(i) != texture)
737		{
738			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME is " << i
739												<< " should be " << texture << tcu::TestLog::EndMessage;
740			return false;
741		}
742		glGetBooleani_v(GL_IMAGE_BINDING_NAME, unit, &b);
743		if (b != (i ? GL_TRUE : GL_FALSE))
744		{
745			m_context.getTestContext().getLog()
746				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_NAME (as boolean) is " << b << " should be "
747				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
748			return false;
749		}
750
751		glGetIntegeri_v(GL_IMAGE_BINDING_LEVEL, unit, &i);
752		if (i != level)
753		{
754			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL is " << i
755												<< " should be " << level << tcu::TestLog::EndMessage;
756			return false;
757		}
758		glGetBooleani_v(GL_IMAGE_BINDING_LEVEL, unit, &b);
759		if (b != (i ? GL_TRUE : GL_FALSE))
760		{
761			m_context.getTestContext().getLog()
762				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LEVEL (as boolean) is " << b << " should be "
763				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
764			return false;
765		}
766
767		glGetIntegeri_v(GL_IMAGE_BINDING_LAYERED, unit, &i);
768		if (i != layered)
769		{
770			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED is " << i
771												<< " should be " << layered << tcu::TestLog::EndMessage;
772			return false;
773		}
774		glGetBooleani_v(GL_IMAGE_BINDING_LAYERED, unit, &b);
775		if (b != (i ? GL_TRUE : GL_FALSE))
776		{
777			m_context.getTestContext().getLog()
778				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYERED (as boolean) is " << b << " should be "
779				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
780			return false;
781		}
782
783		glGetIntegeri_v(GL_IMAGE_BINDING_LAYER, unit, &i);
784		if (i != layer)
785		{
786			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER is " << i
787												<< " should be " << layer << tcu::TestLog::EndMessage;
788			return false;
789		}
790		glGetBooleani_v(GL_IMAGE_BINDING_LAYER, unit, &b);
791		if (b != (i ? GL_TRUE : GL_FALSE))
792		{
793			m_context.getTestContext().getLog()
794				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_LAYER (as boolean) is " << b << " should be "
795				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
796			return false;
797		}
798
799		glGetIntegeri_v(GL_IMAGE_BINDING_ACCESS, unit, &i);
800		if (static_cast<GLenum>(i) != access)
801		{
802			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS is " << i
803												<< " should be " << access << tcu::TestLog::EndMessage;
804			return false;
805		}
806		glGetBooleani_v(GL_IMAGE_BINDING_ACCESS, unit, &b);
807		if (b != (i ? GL_TRUE : GL_FALSE))
808		{
809			m_context.getTestContext().getLog()
810				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_ACCESS (as boolean) is " << b << " should be "
811				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
812			return false;
813		}
814
815		glGetIntegeri_v(GL_IMAGE_BINDING_FORMAT, unit, &i);
816		if (static_cast<GLenum>(i) != format)
817		{
818			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT is " << i
819												<< " should be " << format << tcu::TestLog::EndMessage;
820			return false;
821		}
822		glGetBooleani_v(GL_IMAGE_BINDING_FORMAT, unit, &b);
823		if (b != (i ? GL_TRUE : GL_FALSE))
824		{
825			m_context.getTestContext().getLog()
826				<< tcu::TestLog::Message << "GL_IMAGE_BINDING_FORMAT (as boolean) is " << b << " should be "
827				<< (i ? GL_TRUE : GL_FALSE) << tcu::TestLog::EndMessage;
828			return false;
829		}
830
831		return true;
832	}
833	const char* EnumToString(GLenum e)
834	{
835		switch (e)
836		{
837		case GL_TEXTURE_1D:
838			return "GL_TEXTURE_1D";
839		case GL_TEXTURE_2D:
840			return "GL_TEXTURE_2D";
841		case GL_TEXTURE_3D:
842			return "GL_TEXTURE_3D";
843		case GL_TEXTURE_RECTANGLE:
844			return "GL_TEXTURE_RECTANGLE";
845		case GL_TEXTURE_CUBE_MAP:
846			return "GL_TEXTURE_CUBE_MAP";
847		case GL_TEXTURE_1D_ARRAY:
848			return "GL_TEXTURE_1D_ARRAY";
849		case GL_TEXTURE_2D_ARRAY:
850			return "GL_TEXTURE_2D_ARRAY";
851		case GL_TEXTURE_CUBE_MAP_ARRAY:
852			return "GL_TEXTURE_CUBE_MAP_ARRAY";
853
854		default:
855			assert(0);
856			break;
857		}
858		return NULL;
859	}
860};
861
862template <>
863GLenum ShaderImageLoadStoreBase::Format<vec4>()
864{
865	return GL_RGBA;
866}
867
868template <>
869GLenum ShaderImageLoadStoreBase::Format<ivec4>()
870{
871	return GL_RGBA_INTEGER;
872}
873
874template <>
875GLenum ShaderImageLoadStoreBase::Format<uvec4>()
876{
877	return GL_RGBA_INTEGER;
878}
879
880template <>
881GLenum ShaderImageLoadStoreBase::Format<GLint>()
882{
883	return GL_RED_INTEGER;
884}
885
886template <>
887GLenum ShaderImageLoadStoreBase::Format<GLuint>()
888{
889	return GL_RED_INTEGER;
890}
891
892template <>
893GLenum ShaderImageLoadStoreBase::Type<vec4>()
894{
895	return GL_FLOAT;
896}
897
898template <>
899GLenum ShaderImageLoadStoreBase::Type<ivec4>()
900{
901	return GL_INT;
902}
903
904template <>
905GLenum ShaderImageLoadStoreBase::Type<uvec4>()
906{
907	return GL_UNSIGNED_INT;
908}
909
910template <>
911GLenum ShaderImageLoadStoreBase::Type<GLint>()
912{
913	return GL_INT;
914}
915
916template <>
917GLenum ShaderImageLoadStoreBase::Type<GLuint>()
918{
919	return GL_UNSIGNED_INT;
920}
921
922template <>
923std::string ShaderImageLoadStoreBase::TypePrefix<vec4>()
924{
925	return "";
926}
927
928template <>
929std::string ShaderImageLoadStoreBase::TypePrefix<ivec4>()
930{
931	return "i";
932}
933
934template <>
935std::string ShaderImageLoadStoreBase::TypePrefix<uvec4>()
936{
937	return "u";
938}
939
940template <>
941std::string ShaderImageLoadStoreBase::TypePrefix<GLint>()
942{
943	return "i";
944}
945
946template <>
947std::string ShaderImageLoadStoreBase::TypePrefix<GLuint>()
948{
949	return "u";
950}
951
952template <>
953GLenum ShaderImageLoadStoreBase::ImageType<vec4>(GLenum target)
954{
955	switch (target)
956	{
957	case GL_TEXTURE_1D:
958		return GL_IMAGE_1D;
959	case GL_TEXTURE_2D:
960		return GL_IMAGE_2D;
961	case GL_TEXTURE_3D:
962		return GL_IMAGE_3D;
963	case GL_TEXTURE_RECTANGLE:
964		return GL_IMAGE_2D_RECT;
965	case GL_TEXTURE_CUBE_MAP:
966		return GL_IMAGE_CUBE;
967	case GL_TEXTURE_BUFFER:
968		return GL_IMAGE_BUFFER;
969	case GL_TEXTURE_1D_ARRAY:
970		return GL_IMAGE_1D_ARRAY;
971	case GL_TEXTURE_2D_ARRAY:
972		return GL_IMAGE_2D_ARRAY;
973	case GL_TEXTURE_CUBE_MAP_ARRAY:
974		return GL_IMAGE_CUBE_MAP_ARRAY;
975	case GL_TEXTURE_2D_MULTISAMPLE:
976		return GL_IMAGE_2D_MULTISAMPLE;
977	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
978		return GL_IMAGE_2D_MULTISAMPLE_ARRAY;
979	}
980	assert(0);
981	return 0;
982}
983
984template <>
985GLenum ShaderImageLoadStoreBase::ImageType<ivec4>(GLenum target)
986{
987	switch (target)
988	{
989	case GL_TEXTURE_1D:
990		return GL_INT_IMAGE_1D;
991	case GL_TEXTURE_2D:
992		return GL_INT_IMAGE_2D;
993	case GL_TEXTURE_3D:
994		return GL_INT_IMAGE_3D;
995	case GL_TEXTURE_RECTANGLE:
996		return GL_INT_IMAGE_2D_RECT;
997	case GL_TEXTURE_CUBE_MAP:
998		return GL_INT_IMAGE_CUBE;
999	case GL_TEXTURE_BUFFER:
1000		return GL_INT_IMAGE_BUFFER;
1001	case GL_TEXTURE_1D_ARRAY:
1002		return GL_INT_IMAGE_1D_ARRAY;
1003	case GL_TEXTURE_2D_ARRAY:
1004		return GL_INT_IMAGE_2D_ARRAY;
1005	case GL_TEXTURE_CUBE_MAP_ARRAY:
1006		return GL_INT_IMAGE_CUBE_MAP_ARRAY;
1007	case GL_TEXTURE_2D_MULTISAMPLE:
1008		return GL_INT_IMAGE_2D_MULTISAMPLE;
1009	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1010		return GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1011	}
1012	assert(0);
1013	return 0;
1014}
1015
1016template <>
1017GLenum ShaderImageLoadStoreBase::ImageType<uvec4>(GLenum target)
1018{
1019	switch (target)
1020	{
1021	case GL_TEXTURE_1D:
1022		return GL_UNSIGNED_INT_IMAGE_1D;
1023	case GL_TEXTURE_2D:
1024		return GL_UNSIGNED_INT_IMAGE_2D;
1025	case GL_TEXTURE_3D:
1026		return GL_UNSIGNED_INT_IMAGE_3D;
1027	case GL_TEXTURE_RECTANGLE:
1028		return GL_UNSIGNED_INT_IMAGE_2D_RECT;
1029	case GL_TEXTURE_CUBE_MAP:
1030		return GL_UNSIGNED_INT_IMAGE_CUBE;
1031	case GL_TEXTURE_BUFFER:
1032		return GL_UNSIGNED_INT_IMAGE_BUFFER;
1033	case GL_TEXTURE_1D_ARRAY:
1034		return GL_UNSIGNED_INT_IMAGE_1D_ARRAY;
1035	case GL_TEXTURE_2D_ARRAY:
1036		return GL_UNSIGNED_INT_IMAGE_2D_ARRAY;
1037	case GL_TEXTURE_CUBE_MAP_ARRAY:
1038		return GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY;
1039	case GL_TEXTURE_2D_MULTISAMPLE:
1040		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE;
1041	case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1042		return GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY;
1043	}
1044	assert(0);
1045	return 0;
1046}
1047
1048//-----------------------------------------------------------------------------
1049// 1.1.1 BasicAPIGet
1050//-----------------------------------------------------------------------------
1051class BasicAPIGet : public ShaderImageLoadStoreBase
1052{
1053	virtual long Run()
1054	{
1055		if (!CheckMax(GL_MAX_IMAGE_UNITS, 8))
1056		{
1057			m_context.getTestContext().getLog()
1058				<< tcu::TestLog::Message << "GL_MAX_IMAGE_UNITS value is invalid." << tcu::TestLog::EndMessage;
1059			return ERROR;
1060		}
1061		if (!CheckMax(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, 8))
1062		{
1063			m_context.getTestContext().getLog()
1064				<< tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES value is invalid."
1065				<< tcu::TestLog::EndMessage;
1066			return ERROR;
1067		}
1068		if (!CheckMax(GL_MAX_IMAGE_SAMPLES, 0))
1069		{
1070			m_context.getTestContext().getLog()
1071				<< tcu::TestLog::Message << "GL_MAX_IMAGE_SAMPLES value is invalid." << tcu::TestLog::EndMessage;
1072			return ERROR;
1073		}
1074		if (!CheckMax(GL_MAX_VERTEX_IMAGE_UNIFORMS, 0))
1075		{
1076			m_context.getTestContext().getLog()
1077				<< tcu::TestLog::Message << "GL_MAX_VERTEX_IMAGE_UNIFORMS value is invalid."
1078				<< tcu::TestLog::EndMessage;
1079			return ERROR;
1080		}
1081		if (!CheckMax(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, 0))
1082		{
1083			m_context.getTestContext().getLog()
1084				<< tcu::TestLog::Message << "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS value is invalid."
1085				<< tcu::TestLog::EndMessage;
1086			return ERROR;
1087		}
1088		if (!CheckMax(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, 0))
1089		{
1090			m_context.getTestContext().getLog()
1091				<< tcu::TestLog::Message << "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS value is invalid."
1092				<< tcu::TestLog::EndMessage;
1093			return ERROR;
1094		}
1095		if (!CheckMax(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, 0))
1096		{
1097			m_context.getTestContext().getLog()
1098				<< tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS value is invalid."
1099				<< tcu::TestLog::EndMessage;
1100			return ERROR;
1101		}
1102		if (!CheckMax(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, 8))
1103		{
1104			m_context.getTestContext().getLog()
1105				<< tcu::TestLog::Message << "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is invalid."
1106				<< tcu::TestLog::EndMessage;
1107			return ERROR;
1108		}
1109		if (!CheckMax(GL_MAX_COMBINED_IMAGE_UNIFORMS, 8))
1110		{
1111			m_context.getTestContext().getLog()
1112				<< tcu::TestLog::Message << "GL_MAX_COMBINED_IMAGE_UNIFORMS value is invalid."
1113				<< tcu::TestLog::EndMessage;
1114			return ERROR;
1115		}
1116		return NO_ERROR;
1117	}
1118};
1119//-----------------------------------------------------------------------------
1120// 1.1.2 BasicAPIBind
1121//-----------------------------------------------------------------------------
1122class BasicAPIBind : public ShaderImageLoadStoreBase
1123{
1124	GLuint m_texture;
1125
1126	virtual long Setup()
1127	{
1128		m_texture = 0;
1129		return NO_ERROR;
1130	}
1131
1132	virtual long Run()
1133	{
1134		for (GLuint index = 0; index < 8; ++index)
1135		{
1136			if (!CheckBinding(index, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8))
1137			{
1138				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Binding point " << index
1139													<< " has invalid default state." << tcu::TestLog::EndMessage;
1140				return ERROR;
1141			}
1142		}
1143
1144		glGenTextures(1, &m_texture);
1145		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
1146		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 16, 16, 4, 0, GL_RED, GL_FLOAT, NULL);
1147		glTexImage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 8, 8, 4, 0, GL_RED, GL_FLOAT, NULL);
1148		glTexImage3D(GL_TEXTURE_2D_ARRAY, 2, GL_R32F, 4, 4, 4, 0, GL_RED, GL_FLOAT, NULL);
1149		glTexImage3D(GL_TEXTURE_2D_ARRAY, 3, GL_R32F, 2, 2, 4, 0, GL_RED, GL_FLOAT, NULL);
1150		glTexImage3D(GL_TEXTURE_2D_ARRAY, 4, GL_R32F, 1, 1, 4, 0, GL_RED, GL_FLOAT, NULL);
1151		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1152
1153		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
1154		if (!CheckBinding(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F))
1155			return ERROR;
1156
1157		glBindImageTexture(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8);
1158		if (!CheckBinding(1, m_texture, 1, GL_TRUE, 1, GL_WRITE_ONLY, GL_RGBA8))
1159			return ERROR;
1160
1161		glBindImageTexture(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16);
1162		if (!CheckBinding(4, m_texture, 3, GL_FALSE, 2, GL_READ_ONLY, GL_RG16))
1163			return ERROR;
1164
1165		glBindImageTexture(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I);
1166		if (!CheckBinding(7, m_texture, 4, GL_FALSE, 3, GL_READ_ONLY, GL_R32I))
1167			return ERROR;
1168
1169		glDeleteTextures(1, &m_texture);
1170		m_texture = 0;
1171
1172		for (GLuint index = 0; index < 8; ++index)
1173		{
1174			GLint name;
1175			glGetIntegeri_v(GL_IMAGE_BINDING_NAME, index, &name);
1176			if (name != 0)
1177			{
1178				m_context.getTestContext().getLog()
1179					<< tcu::TestLog::Message << "Binding point " << index
1180					<< " should be set to 0 after texture deletion." << tcu::TestLog::EndMessage;
1181				return ERROR;
1182			}
1183		}
1184
1185		return NO_ERROR;
1186	}
1187
1188	virtual long Cleanup()
1189	{
1190		glDeleteTextures(1, &m_texture);
1191		return NO_ERROR;
1192	}
1193};
1194//-----------------------------------------------------------------------------
1195// 1.1.3 BasicAPIBarrier
1196//-----------------------------------------------------------------------------
1197class BasicAPIBarrier : public ShaderImageLoadStoreBase
1198{
1199	virtual long Run()
1200	{
1201		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
1202		glMemoryBarrier(GL_ELEMENT_ARRAY_BARRIER_BIT);
1203		glMemoryBarrier(GL_UNIFORM_BARRIER_BIT);
1204		glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
1205		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1206		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
1207		glMemoryBarrier(GL_PIXEL_BUFFER_BARRIER_BIT);
1208		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1209		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1210		glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1211		glMemoryBarrier(GL_TRANSFORM_FEEDBACK_BARRIER_BIT);
1212		glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
1213
1214		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1215						GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1216						GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1217						GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1218
1219		glMemoryBarrier(GL_ALL_BARRIER_BITS);
1220
1221		return NO_ERROR;
1222	}
1223};
1224//-----------------------------------------------------------------------------
1225// 1.1.4 BasicAPITexParam
1226//-----------------------------------------------------------------------------
1227class BasicAPITexParam : public ShaderImageLoadStoreBase
1228{
1229	GLuint m_texture;
1230
1231	virtual long Setup()
1232	{
1233		m_texture = 0;
1234		return NO_ERROR;
1235	}
1236
1237	virtual long Run()
1238	{
1239		glGenTextures(1, &m_texture);
1240		glBindTexture(GL_TEXTURE_2D, m_texture);
1241		glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 16, 16, 0, GL_RED, GL_FLOAT, NULL);
1242
1243		GLint   i;
1244		GLfloat f;
1245		GLuint  ui;
1246
1247		glGetTexParameteriv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1248		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1249		{
1250			m_context.getTestContext().getLog()
1251				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1252				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1253				<< tcu::TestLog::EndMessage;
1254			return ERROR;
1255		}
1256		glGetTexParameterfv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &f);
1257		if (static_cast<GLenum>(f) != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1258		{
1259			m_context.getTestContext().getLog()
1260				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1261				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1262				<< tcu::TestLog::EndMessage;
1263			return ERROR;
1264		}
1265		glGetTexParameterIiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &i);
1266		if (i != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1267		{
1268			m_context.getTestContext().getLog()
1269				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1270				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1271				<< tcu::TestLog::EndMessage;
1272			return ERROR;
1273		}
1274		glGetTexParameterIuiv(GL_TEXTURE_2D, GL_IMAGE_FORMAT_COMPATIBILITY_TYPE, &ui);
1275		if (ui != GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE)
1276		{
1277			m_context.getTestContext().getLog()
1278				<< tcu::TestLog::Message << "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE should equal to "
1279				<< "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE for textures allocated by the GL."
1280				<< tcu::TestLog::EndMessage;
1281			return ERROR;
1282		}
1283
1284		return NO_ERROR;
1285	}
1286
1287	virtual long Cleanup()
1288	{
1289		glDeleteTextures(1, &m_texture);
1290		return NO_ERROR;
1291	}
1292};
1293//-----------------------------------------------------------------------------
1294// 1.2.1 BasicAllFormatsStore
1295//-----------------------------------------------------------------------------
1296class BasicAllFormatsStore : public ShaderImageLoadStoreBase
1297{
1298	GLuint m_vao;
1299	GLuint m_vbo;
1300
1301	virtual long Setup()
1302	{
1303		m_vao = 0;
1304		m_vbo = 0;
1305		return NO_ERROR;
1306	}
1307
1308	virtual long Run()
1309	{
1310		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1311
1312		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1313			return ERROR;
1314		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1315			return ERROR;
1316		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1317			return ERROR;
1318
1319		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1320			return ERROR;
1321		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1322			return ERROR;
1323		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1324			return ERROR;
1325
1326		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1327			return ERROR;
1328		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1329			return ERROR;
1330		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1331			return ERROR;
1332
1333		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1334			return ERROR;
1335
1336		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1337			return ERROR;
1338		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1339			return ERROR;
1340		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1341			return ERROR;
1342
1343		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1344			return ERROR;
1345		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1346			return ERROR;
1347		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1348			return ERROR;
1349
1350		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1351			return ERROR;
1352		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1353			return ERROR;
1354		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1355			return ERROR;
1356		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1357			return ERROR;
1358
1359		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1360			return ERROR;
1361		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1362			return ERROR;
1363		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1364			return ERROR;
1365
1366		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1367			return ERROR;
1368		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1369			return ERROR;
1370		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1371			return ERROR;
1372
1373		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1374			return ERROR;
1375		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1376			return ERROR;
1377		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1378			return ERROR;
1379		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1380			return ERROR;
1381
1382		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1383			return ERROR;
1384		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1385			return ERROR;
1386		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1387			return ERROR;
1388
1389		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1390			return ERROR;
1391		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1392			return ERROR;
1393		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1394			return ERROR;
1395
1396		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1397			return ERROR;
1398		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1399			return ERROR;
1400		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1401			return ERROR;
1402
1403		return NO_ERROR;
1404	}
1405
1406	template <typename T>
1407	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1408	{
1409		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1410							 "  gl_Position = i_position;" NL "}";
1411		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
1412		const int	  kSize   = 16;
1413		std::vector<T> data(kSize * kSize);
1414		GLuint		   texture;
1415		glGenTextures(1, &texture);
1416
1417		for (GLuint unit = 0; unit < 8; ++unit)
1418		{
1419			glBindTexture(GL_TEXTURE_2D, texture);
1420			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1421			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1422			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1423			glBindTexture(GL_TEXTURE_2D, 0);
1424
1425			glViewport(0, 0, kSize, kSize);
1426			glUseProgram(program);
1427			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
1428			glBindVertexArray(m_vao);
1429			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1430
1431			glBindTexture(GL_TEXTURE_2D, texture);
1432			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1433			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
1434
1435			for (int i = 0; i < kSize * kSize; ++i)
1436			{
1437				if (!Equal(data[i], expected_value, internalformat))
1438				{
1439					glDeleteTextures(1, &texture);
1440					glUseProgram(0);
1441					glDeleteProgram(program);
1442					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[i])
1443														<< ". Value should be: " << ToString(expected_value)
1444														<< ". Format is: " << FormatEnumToString(internalformat)
1445														<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1446					return false;
1447				}
1448			}
1449
1450			if (unit < 7)
1451			{
1452				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1453			}
1454		}
1455
1456		glDeleteTextures(1, &texture);
1457		glUseProgram(0);
1458		glDeleteProgram(program);
1459
1460		return true;
1461	}
1462
1463	virtual long Cleanup()
1464	{
1465		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1466		glDeleteVertexArrays(1, &m_vao);
1467		glDeleteBuffers(1, &m_vbo);
1468		return NO_ERROR;
1469	}
1470
1471	template <typename T>
1472	std::string GenFS(GLenum internalformat, const T& value)
1473	{
1474		std::ostringstream os;
1475		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1476		   << TypePrefix<T>() << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
1477								 "  imageStore(g_image, coord, "
1478		   << TypePrefix<T>() << "vec4" << value << ");" NL "  discard;" NL "}";
1479		return os.str();
1480	}
1481};
1482//-----------------------------------------------------------------------------
1483// 1.2.2 BasicAllFormatsLoad
1484//-----------------------------------------------------------------------------
1485class BasicAllFormatsLoad : public ShaderImageLoadStoreBase
1486{
1487	GLuint m_vao;
1488	GLuint m_vbo;
1489
1490	virtual long Setup()
1491	{
1492		m_vao = 0;
1493		m_vbo = 0;
1494		return NO_ERROR;
1495	}
1496
1497	virtual long Run()
1498	{
1499		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
1500
1501		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1502			return ERROR;
1503		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1504			return ERROR;
1505		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1506			return ERROR;
1507
1508		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1509			return ERROR;
1510		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1511			return ERROR;
1512		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1513			return ERROR;
1514
1515		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1516			return ERROR;
1517		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1518			return ERROR;
1519		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1520			return ERROR;
1521
1522		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1523			return ERROR;
1524
1525		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1526			return ERROR;
1527		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1528			return ERROR;
1529		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1530			return ERROR;
1531
1532		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1533			return ERROR;
1534		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1535			return ERROR;
1536		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1537			return ERROR;
1538
1539		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1540			return ERROR;
1541		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1542			return ERROR;
1543		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1544			return ERROR;
1545		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1546			return ERROR;
1547
1548		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1549			return ERROR;
1550		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1551			return ERROR;
1552		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1553			return ERROR;
1554
1555		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1556			return ERROR;
1557		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1558			return ERROR;
1559		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1560			return ERROR;
1561
1562		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1563			return ERROR;
1564		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1565			return ERROR;
1566		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1567			return ERROR;
1568		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1569			return ERROR;
1570
1571		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1572			return ERROR;
1573		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1574			return ERROR;
1575		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1576			return ERROR;
1577
1578		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1579			return ERROR;
1580		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1581			return ERROR;
1582		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1583			return ERROR;
1584
1585		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1586			return ERROR;
1587		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1588			return ERROR;
1589		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1590			return ERROR;
1591
1592		return NO_ERROR;
1593	}
1594
1595	template <typename T>
1596	bool Read(GLenum internalformat, const T& value, const T& expected_value)
1597	{
1598		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
1599							 "  gl_Position = i_position;" NL "}";
1600		const GLuint   program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
1601		const int	  kSize   = 16;
1602		std::vector<T> data(kSize * kSize, value);
1603		GLuint		   texture;
1604		glGenTextures(1, &texture);
1605
1606		for (GLuint unit = 0; unit < 8; ++unit)
1607		{
1608			glBindTexture(GL_TEXTURE_2D, texture);
1609			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1610			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1611			glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
1612			glBindTexture(GL_TEXTURE_2D, 0);
1613
1614			glViewport(0, 0, kSize, kSize);
1615			glClear(GL_COLOR_BUFFER_BIT);
1616			glUseProgram(program);
1617			glBindImageTexture(unit, texture, 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
1618			glBindVertexArray(m_vao);
1619			glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1620
1621			if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
1622			{
1623				glDeleteTextures(1, &texture);
1624				glUseProgram(0);
1625				glDeleteProgram(program);
1626				m_context.getTestContext().getLog()
1627					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
1628					<< ". Unit is: " << unit << tcu::TestLog::EndMessage;
1629				return false;
1630			}
1631
1632			if (unit < 7)
1633			{
1634				glUniform1i(glGetUniformLocation(program, "g_image"), static_cast<GLint>(unit + 1));
1635			}
1636		}
1637
1638		glDeleteTextures(1, &texture);
1639		glUseProgram(0);
1640		glDeleteProgram(program);
1641
1642		return true;
1643	}
1644
1645	virtual long Cleanup()
1646	{
1647		glViewport(0, 0, getWindowWidth(), getWindowHeight());
1648		glDeleteVertexArrays(1, &m_vao);
1649		glDeleteBuffers(1, &m_vbo);
1650		return NO_ERROR;
1651	}
1652
1653	template <typename T>
1654	std::string GenFS(GLenum internalformat, const T& expected_value)
1655	{
1656		std::ostringstream os;
1657		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
1658		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
1659		   << "image2D g_image;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
1660		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
1661		   << expected_value
1662		   << ") 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 "}";
1663		return os.str();
1664	}
1665};
1666//-----------------------------------------------------------------------------
1667// 1.2.3 BasicAllFormatsStoreGeometryStages
1668//-----------------------------------------------------------------------------
1669class BasicAllFormatsStoreGeometryStages : public ShaderImageLoadStoreBase
1670{
1671	GLuint m_vao;
1672
1673	virtual long Setup()
1674	{
1675		glGenVertexArrays(1, &m_vao);
1676		return NO_ERROR;
1677	}
1678
1679	virtual long Run()
1680	{
1681		if (!SupportedInGeomStages(1))
1682			return NOT_SUPPORTED;
1683		glEnable(GL_RASTERIZER_DISCARD);
1684
1685		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1686			return ERROR;
1687		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1688			return ERROR;
1689		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1690			return ERROR;
1691
1692		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1693			return ERROR;
1694		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1695			return ERROR;
1696		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1697			return ERROR;
1698
1699		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1700			return ERROR;
1701		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1702			return ERROR;
1703		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1704			return ERROR;
1705
1706		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1707			return ERROR;
1708
1709		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1710			return ERROR;
1711		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1712			return ERROR;
1713		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1714			return ERROR;
1715
1716		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1717			return ERROR;
1718		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1719			return ERROR;
1720		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1721			return ERROR;
1722
1723		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1724			return ERROR;
1725		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1726			return ERROR;
1727		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1728			return ERROR;
1729		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1730			return ERROR;
1731
1732		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1733			return ERROR;
1734		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1735			return ERROR;
1736		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1737			return ERROR;
1738
1739		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1740			return ERROR;
1741		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1742			return ERROR;
1743		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1744			return ERROR;
1745
1746		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1747			return ERROR;
1748		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1749			return ERROR;
1750		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1751			return ERROR;
1752		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1753			return ERROR;
1754
1755		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1756			return ERROR;
1757		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1758			return ERROR;
1759		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1760			return ERROR;
1761
1762		if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1763			return ERROR;
1764		if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1765			return ERROR;
1766		if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1767			return ERROR;
1768
1769		if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1770			return ERROR;
1771		if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1772			return ERROR;
1773		if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1774			return ERROR;
1775
1776		return NO_ERROR;
1777	}
1778
1779	template <typename T>
1780	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
1781	{
1782		const GLuint program =
1783			BuildProgram(GenVS(internalformat, write_value).c_str(), GenTCS(internalformat, write_value).c_str(),
1784						 GenTES(internalformat, write_value).c_str(), GenGS(internalformat, write_value).c_str(), NULL);
1785		const int	  kSize = 1;
1786		std::vector<T> data(kSize * kSize);
1787		GLuint		   texture[4];
1788		glGenTextures(4, texture);
1789
1790		for (int i = 0; i < 4; ++i)
1791		{
1792			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1793			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1794			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1795			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
1796		}
1797		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1798
1799		glUseProgram(program);
1800		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
1801		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
1802		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
1803		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
1804		for (GLuint i = 0; i < 4; ++i)
1805		{
1806			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
1807		}
1808		glBindVertexArray(m_vao);
1809		glPatchParameteri(GL_PATCH_VERTICES, 1);
1810		glDrawArrays(GL_PATCHES, 0, 1);
1811		glPatchParameteri(GL_PATCH_VERTICES, 3);
1812
1813		for (int i = 0; i < 4; ++i)
1814		{
1815			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
1816			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
1817			glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
1818
1819			if (!Equal(data[0], expected_value, internalformat))
1820			{
1821				glDeleteTextures(4, texture);
1822				glUseProgram(0);
1823				glDeleteProgram(program);
1824				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Value is: " << ToString(data[0])
1825													<< ". Value should be: " << ToString(expected_value)
1826													<< ". Format is: " << FormatEnumToString(internalformat)
1827													<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
1828				return false;
1829			}
1830		}
1831		glDeleteTextures(4, texture);
1832		glUseProgram(0);
1833		glDeleteProgram(program);
1834		return true;
1835	}
1836
1837	virtual long Cleanup()
1838	{
1839		glDisable(GL_RASTERIZER_DISCARD);
1840		glDeleteVertexArrays(1, &m_vao);
1841		return NO_ERROR;
1842	}
1843
1844	template <typename T>
1845	std::string GenVS(GLenum internalformat, const T& value)
1846	{
1847		std::ostringstream os;
1848		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
1849		   << TypePrefix<T>() << "image2DArray g_image0;" NL "void main() {" NL
1850								 "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  imageStore(g_image0, coord, "
1851		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1852		return os.str();
1853	}
1854
1855	template <typename T>
1856	std::string GenTCS(GLenum internalformat, const T& value)
1857	{
1858		std::ostringstream os;
1859		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
1860		   << ") writeonly uniform " << TypePrefix<T>()
1861		   << "image2DArray g_image1;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
1862			  "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
1863			  "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
1864			  "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  imageStore(g_image1, coord, "
1865		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1866		return os.str();
1867	}
1868
1869	template <typename T>
1870	std::string GenTES(GLenum internalformat, const T& value)
1871	{
1872		std::ostringstream os;
1873		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
1874		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1875		   << "image2DArray g_image2;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL
1876			  "  imageStore(g_image2, coord, "
1877		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1878		return os.str();
1879	}
1880
1881	template <typename T>
1882	std::string GenGS(GLenum internalformat, const T& value)
1883	{
1884		std::ostringstream os;
1885		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
1886		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
1887		   << "image2DArray g_image3;" NL "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL
1888			  "  imageStore(g_image3, coord, "
1889		   << TypePrefix<T>() << "vec4" << value << ");" NL "}";
1890		return os.str();
1891	}
1892};
1893//-----------------------------------------------------------------------------
1894// 1.2.4 BasicAllFormatsLoadGeometryStages
1895//-----------------------------------------------------------------------------
1896class BasicAllFormatsLoadGeometryStages : public ShaderImageLoadStoreBase
1897{
1898	GLuint m_vao;
1899
1900	virtual long Setup()
1901	{
1902		glGenVertexArrays(1, &m_vao);
1903		return NO_ERROR;
1904	}
1905
1906	virtual long Run()
1907	{
1908		if (!SupportedInGeomStages(2))
1909			return NOT_SUPPORTED;
1910		glEnable(GL_RASTERIZER_DISCARD);
1911
1912		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1913			return ERROR;
1914		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1915			return ERROR;
1916		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1917			return ERROR;
1918
1919		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
1920			return ERROR;
1921		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
1922			return ERROR;
1923		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1924			return ERROR;
1925
1926		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1927			return ERROR;
1928		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1929			return ERROR;
1930		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1931			return ERROR;
1932
1933		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
1934			return ERROR;
1935
1936		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1937			return ERROR;
1938		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1939			return ERROR;
1940		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1941			return ERROR;
1942
1943		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
1944			return ERROR;
1945		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
1946			return ERROR;
1947		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
1948			return ERROR;
1949
1950		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1951			return ERROR;
1952		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1953			return ERROR;
1954		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1955			return ERROR;
1956		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1957			return ERROR;
1958
1959		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1960			return ERROR;
1961		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1962			return ERROR;
1963		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1964			return ERROR;
1965
1966		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
1967			return ERROR;
1968		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
1969			return ERROR;
1970		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
1971			return ERROR;
1972
1973		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
1974			return ERROR;
1975		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
1976			return ERROR;
1977		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1978			return ERROR;
1979		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1980			return ERROR;
1981
1982		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
1983			return ERROR;
1984		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
1985			return ERROR;
1986		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
1987			return ERROR;
1988
1989		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1990			return ERROR;
1991		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1992			return ERROR;
1993		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
1994			return ERROR;
1995
1996		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
1997			return ERROR;
1998		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
1999			return ERROR;
2000		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2001			return ERROR;
2002
2003		return NO_ERROR;
2004	}
2005
2006	template <typename T>
2007	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2008	{
2009		const GLuint program = BuildProgram(
2010			GenVS(internalformat, expected_value).c_str(), GenTCS(internalformat, expected_value).c_str(),
2011			GenTES(internalformat, expected_value).c_str(), GenGS(internalformat, expected_value).c_str(), NULL);
2012		const int	  kSize = 1;
2013		std::vector<T> data(kSize * kSize, value);
2014		GLuint		   texture[8];
2015		glGenTextures(8, texture);
2016
2017		for (int i = 0; i < 4; ++i)
2018		{
2019			glBindTexture(GL_TEXTURE_2D_ARRAY, texture[i]);
2020			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2021			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2022			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 1, 0, Format<T>(), Type<T>(), &data[0]);
2023		}
2024		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2025		vec4 zero(0);
2026		for (int i = 4; i < 8; ++i)
2027		{
2028			glBindTexture(GL_TEXTURE_2D, texture[i]);
2029			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2030			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2031			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &zero);
2032		}
2033		glBindTexture(GL_TEXTURE_2D, 0);
2034
2035		glUseProgram(program);
2036		glUniform1i(glGetUniformLocation(program, "g_image0"), 0);
2037		glUniform1i(glGetUniformLocation(program, "g_image1"), 1);
2038		glUniform1i(glGetUniformLocation(program, "g_image2"), 2);
2039		glUniform1i(glGetUniformLocation(program, "g_image3"), 3);
2040		glUniform1i(glGetUniformLocation(program, "g_image0_result"), 4);
2041		glUniform1i(glGetUniformLocation(program, "g_image1_result"), 5);
2042		glUniform1i(glGetUniformLocation(program, "g_image2_result"), 6);
2043		glUniform1i(glGetUniformLocation(program, "g_image3_result"), 7);
2044
2045		for (GLuint i = 0; i < 4; ++i)
2046		{
2047			glBindImageTexture(i, texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2048		}
2049		for (GLuint i = 4; i < 8; ++i)
2050		{
2051			glBindImageTexture(i, texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
2052		}
2053		glBindVertexArray(m_vao);
2054		glPatchParameteri(GL_PATCH_VERTICES, 1);
2055		glDrawArrays(GL_PATCHES, 0, 1);
2056		glPatchParameteri(GL_PATCH_VERTICES, 3);
2057
2058		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
2059		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
2060		vec4					 g_color_eps  = vec4(
2061			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
2062			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
2063
2064		for (int i = 0; i < 4; ++i)
2065		{
2066			glBindTexture(GL_TEXTURE_2D, texture[i + 4]);
2067			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2068			vec4 result;
2069			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &result[0]);
2070			if (!ColorEqual(result, vec4(0, 1, 0, 1), g_color_eps))
2071			{
2072				glDeleteTextures(8, texture);
2073				glUseProgram(0);
2074				glDeleteProgram(program);
2075				m_context.getTestContext().getLog()
2076					<< tcu::TestLog::Message << "Bad load value. Format is: " << FormatEnumToString(internalformat)
2077					<< ". Stage is: " << StageName(i) << tcu::TestLog::EndMessage;
2078				return false;
2079			}
2080		}
2081		glDeleteTextures(8, texture);
2082		glUseProgram(0);
2083		glDeleteProgram(program);
2084		return true;
2085	}
2086
2087	virtual long Cleanup()
2088	{
2089		glDisable(GL_RASTERIZER_DISCARD);
2090		glDeleteVertexArrays(1, &m_vao);
2091		return NO_ERROR;
2092	}
2093
2094	template <typename T>
2095	std::string GenVS(GLenum internalformat, const T& expected_value)
2096	{
2097		std::ostringstream os;
2098		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
2099		   << TypePrefix<T>()
2100		   << "image2DArray g_image0;" NL "layout(rgba32f) writeonly uniform image2D g_image0_result;" NL
2101			  "void main() {" NL "  ivec3 coord = ivec3(gl_VertexID, 0, 0);" NL "  "
2102		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image0, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2103		   << expected_value << ") imageStore(g_image0_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2104								"  else imageStore(g_image0_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2105		return os.str();
2106	}
2107
2108	template <typename T>
2109	std::string GenTCS(GLenum internalformat, const T& expected_value)
2110	{
2111		std::ostringstream os;
2112		os << "#version 420 core" NL "layout(vertices = 1) out;" NL "layout(" << FormatEnumToString(internalformat)
2113		   << ") readonly uniform " << TypePrefix<T>()
2114		   << "image2DArray g_image1;" NL "layout(rgba32f) writeonly uniform image2D g_image1_result;" NL
2115			  "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL "  gl_TessLevelInner[1] = 1;" NL
2116			  "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL "  gl_TessLevelOuter[2] = 1;" NL
2117			  "  gl_TessLevelOuter[3] = 1;" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2118		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image1, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2119		   << expected_value << ") imageStore(g_image1_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2120								"  else imageStore(g_image1_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2121		return os.str();
2122	}
2123
2124	template <typename T>
2125	std::string GenTES(GLenum internalformat, const T& expected_value)
2126	{
2127		std::ostringstream os;
2128		os << "#version 420 core" NL "layout(triangles, point_mode) in;" NL "layout("
2129		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2130		   << "image2DArray g_image2;" NL "layout(rgba32f) writeonly uniform image2D g_image2_result;" NL
2131			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveID, 0, 0);" NL "  "
2132		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image2, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2133		   << expected_value << ") imageStore(g_image2_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2134								"  else imageStore(g_image2_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2135		return os.str();
2136	}
2137
2138	template <typename T>
2139	std::string GenGS(GLenum internalformat, const T& expected_value)
2140	{
2141		std::ostringstream os;
2142		os << "#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "layout("
2143		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2144		   << "image2DArray g_image3;" NL "layout(rgba32f) writeonly uniform image2D g_image3_result;" NL
2145			  "void main() {" NL "  ivec3 coord = ivec3(gl_PrimitiveIDIn, 0, 0);" NL "  "
2146		   << TypePrefix<T>() << "vec4 v = imageLoad(g_image3, coord);" NL "  if (v != " << TypePrefix<T>() << "vec4"
2147		   << expected_value << ") imageStore(g_image3_result, coord.xy, vec4(1.0, 0.0, 0.0, 1.0));" NL
2148								"  else imageStore(g_image3_result, coord.xy, vec4(0.0, 1.0, 0.0, 1.0));" NL "}";
2149		return os.str();
2150	}
2151};
2152//-----------------------------------------------------------------------------
2153// 1.2.5 BasicAllFormatsLoadStoreComputeStage
2154//-----------------------------------------------------------------------------
2155class BasicAllFormatsLoadStoreComputeStage : public ShaderImageLoadStoreBase
2156{
2157	virtual long Run()
2158	{
2159		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
2160		{
2161			m_context.getTestContext().getLog()
2162				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
2163				<< tcu::TestLog::EndMessage;
2164			return NOT_SUPPORTED;
2165		}
2166
2167		if (!Read(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2168			return ERROR;
2169		if (!Read(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2170			return ERROR;
2171		if (!Read(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2172			return ERROR;
2173
2174		if (!Read(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
2175			return ERROR;
2176		if (!Read(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
2177			return ERROR;
2178		if (!Read(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2179			return ERROR;
2180
2181		if (!Read(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2182			return ERROR;
2183		if (!Read(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2184			return ERROR;
2185		if (!Read(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2186			return ERROR;
2187
2188		if (!Read(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
2189			return ERROR;
2190
2191		if (!Read(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2192			return ERROR;
2193		if (!Read(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2194			return ERROR;
2195		if (!Read(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2196			return ERROR;
2197
2198		if (!Read(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2199			return ERROR;
2200		if (!Read(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
2201			return ERROR;
2202		if (!Read(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
2203			return ERROR;
2204
2205		if (!Read(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2206			return ERROR;
2207		if (!Read(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2208			return ERROR;
2209		if (!Read(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2210			return ERROR;
2211		if (!Read(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2212			return ERROR;
2213
2214		if (!Read(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2215			return ERROR;
2216		if (!Read(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2217			return ERROR;
2218		if (!Read(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2219			return ERROR;
2220
2221		if (!Read(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
2222			return ERROR;
2223		if (!Read(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
2224			return ERROR;
2225		if (!Read(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
2226			return ERROR;
2227
2228		if (!Read(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
2229			return ERROR;
2230		if (!Read(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
2231			return ERROR;
2232		if (!Read(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2233			return ERROR;
2234		if (!Read(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2235			return ERROR;
2236
2237		if (!Read(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
2238			return ERROR;
2239		if (!Read(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
2240			return ERROR;
2241		if (!Read(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
2242			return ERROR;
2243
2244		if (!Read(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2245			return ERROR;
2246		if (!Read(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2247			return ERROR;
2248		if (!Read(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2249			return ERROR;
2250
2251		if (!Read(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
2252			return ERROR;
2253		if (!Read(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
2254			return ERROR;
2255		if (!Read(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
2256			return ERROR;
2257
2258		return NO_ERROR;
2259	}
2260
2261	template <typename T>
2262	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2263	{
2264		GLuint			  program;
2265		std::string		  source = GenCS<T>(internalformat);
2266		const char* const src	= source.c_str();
2267		GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
2268		glShaderSource(sh, 1, &src, NULL);
2269		glCompileShader(sh);
2270		program = glCreateProgram();
2271		glAttachShader(program, sh);
2272		glLinkProgram(program);
2273		glDeleteShader(sh);
2274
2275		const int	  kSize = 1;
2276		std::vector<T> data(kSize * kSize, value);
2277		GLuint		   texture[2];
2278		glGenTextures(2, texture);
2279
2280		glBindTexture(GL_TEXTURE_2D, texture[0]);
2281		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2282		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2283		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2284		glBindTexture(GL_TEXTURE_2D, texture[1]);
2285		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2286		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2287		vec4 zero(0);
2288		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &zero);
2289
2290		glBindTexture(GL_TEXTURE_2D, 0);
2291
2292		glUseProgram(program);
2293		glUniform1i(glGetUniformLocation(program, "g_image_read"), 0);
2294		glUniform1i(glGetUniformLocation(program, "g_image_write"), 1);
2295
2296		glBindImageTexture(0, texture[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2297		glBindImageTexture(1, texture[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2298
2299		glDispatchCompute(1, 1, 1);
2300
2301		for (int i = 0; i < 2; ++i)
2302		{
2303			glBindTexture(GL_TEXTURE_2D, texture[i]);
2304			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2305			glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2306
2307			if (!Equal(data[0], expected_value, internalformat))
2308			{
2309				glDeleteTextures(4, texture);
2310				glUseProgram(0);
2311				glDeleteProgram(program);
2312				m_context.getTestContext().getLog()
2313					<< tcu::TestLog::Message << "Value is: " << ToString(data[0])
2314					<< ". Value should be: " << ToString(expected_value)
2315					<< ". Format is: " << FormatEnumToString(internalformat) << tcu::TestLog::EndMessage;
2316				return false;
2317			}
2318		}
2319		glDeleteTextures(2, texture);
2320		glUseProgram(0);
2321		glDeleteProgram(program);
2322		return true;
2323	}
2324
2325	template <typename T>
2326	std::string GenCS(GLenum internalformat)
2327	{
2328		std::ostringstream os;
2329		os << "#version 420 core" NL "#extension GL_ARB_compute_shader : require" NL "layout(local_size_x = 1) in;" NL
2330			  "layout("
2331		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
2332		   << "image2D g_image_read;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2333		   << TypePrefix<T>() << "image2D g_image_write;" NL "void main() {" NL
2334								 "  ivec2 coord = ivec2(int(gl_GlobalInvocationID.x), 0);" NL "  "
2335		   << TypePrefix<T>()
2336		   << "vec4 v = imageLoad(g_image_read, coord);" NL "  imageStore(g_image_write, coord, v);" NL "}";
2337		return os.str();
2338	}
2339};
2340//-----------------------------------------------------------------------------
2341// 1.3.1 BasicAllTargetsStore
2342//-----------------------------------------------------------------------------
2343class BasicAllTargetsStore : public ShaderImageLoadStoreBase
2344{
2345	GLuint m_vao;
2346	GLuint m_vbo;
2347
2348	virtual long Setup()
2349	{
2350		m_vao = 0;
2351		m_vbo = 0;
2352		return NO_ERROR;
2353	}
2354
2355	virtual long Run()
2356	{
2357		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2358
2359		if (!Write(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2360			return ERROR;
2361		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2362			return ERROR;
2363		if (!Write(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2364			return ERROR;
2365
2366		if (!WriteCubeArray(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2367			return ERROR;
2368		if (!WriteCubeArray(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2369			return ERROR;
2370		if (!WriteCubeArray(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2371			return ERROR;
2372
2373		if (SupportedSamples(4))
2374		{
2375			if (!WriteMS(GL_RGBA32F, vec4(-1.0f, 2.0f, 3.0f, -4.0f), vec4(-1.0f, 2.0f, 3.0f, -4.0f)))
2376				return ERROR;
2377
2378			GLint isamples;
2379			glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
2380			if (isamples >= 4)
2381			{
2382				if (!WriteMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
2383					return ERROR;
2384				if (!WriteMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
2385					return ERROR;
2386			}
2387		}
2388		return NO_ERROR;
2389	}
2390
2391	virtual long Cleanup()
2392	{
2393		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2394		glDeleteVertexArrays(1, &m_vao);
2395		glDeleteBuffers(1, &m_vbo);
2396		return NO_ERROR;
2397	}
2398
2399	template <typename T>
2400	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
2401	{
2402		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2403							 "  gl_Position = i_position;" NL "}";
2404		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, write_value).c_str());
2405		GLuint		 textures[8];
2406		GLuint		 buffer;
2407		glGenTextures(8, textures);
2408		glGenBuffers(1, &buffer);
2409
2410		const int	  kSize = 16;
2411		std::vector<T> data(kSize * kSize * 2);
2412
2413		glBindTexture(GL_TEXTURE_1D, textures[0]);
2414		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2415		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2416		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2417		glBindTexture(GL_TEXTURE_1D, 0);
2418
2419		glBindTexture(GL_TEXTURE_2D, textures[1]);
2420		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2421		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2422		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2423		glBindTexture(GL_TEXTURE_2D, 0);
2424
2425		glBindTexture(GL_TEXTURE_3D, textures[2]);
2426		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2427		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2428		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2429		glBindTexture(GL_TEXTURE_3D, 0);
2430
2431		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2432		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2433		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2434		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2435		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2436
2437		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2438		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2439		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2440		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2441					 &data[0]);
2442		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2443					 &data[0]);
2444		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2445					 &data[0]);
2446		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2447					 &data[0]);
2448		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2449					 &data[0]);
2450		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
2451					 &data[0]);
2452		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2453
2454		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2455		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2456		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2457		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2458		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2459		glBindTexture(GL_TEXTURE_BUFFER, 0);
2460
2461		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2462		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2463		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2464		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2465		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2466
2467		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2468		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2469		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2470		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2471		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2472
2473		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2474		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2475		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2476		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2477		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2478		glBindImageTexture(5, textures[5], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2479		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2480		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2481
2482		glUseProgram(program);
2483		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
2484		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
2485		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
2486		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
2487		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
2488		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
2489		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
2490		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
2491
2492		glBindVertexArray(m_vao);
2493		glViewport(0, 0, kSize, kSize);
2494		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2495
2496		bool status = true;
2497
2498		glBindTexture(GL_TEXTURE_1D, textures[0]);
2499		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2500		glGetTexImage(GL_TEXTURE_1D, 0, Format<T>(), Type<T>(), &data[0]);
2501		glBindTexture(GL_TEXTURE_1D, 0);
2502		for (int i = 0; i < kSize; ++i)
2503		{
2504			if (!tcu::allEqual(data[i], expected_value))
2505			{
2506				status = false;
2507				m_context.getTestContext().getLog()
2508					<< tcu::TestLog::Message << "GL_TEXTURE_1D target failed. Value is: " << ToString(data[i])
2509					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2510				break;
2511			}
2512		}
2513		std::fill(data.begin(), data.end(), T(0));
2514
2515		glBindTexture(GL_TEXTURE_2D, textures[1]);
2516		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2517		glGetTexImage(GL_TEXTURE_2D, 0, Format<T>(), Type<T>(), &data[0]);
2518		glBindTexture(GL_TEXTURE_2D, 0);
2519		for (int i = 0; i < kSize * kSize; ++i)
2520		{
2521			if (!tcu::allEqual(data[i], expected_value))
2522			{
2523				status = false;
2524				m_context.getTestContext().getLog()
2525					<< tcu::TestLog::Message << "GL_TEXTURE_2D target failed. Value is: " << ToString(data[i])
2526					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2527				break;
2528			}
2529		}
2530
2531		glBindTexture(GL_TEXTURE_3D, textures[2]);
2532		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2533		glGetTexImage(GL_TEXTURE_3D, 0, Format<T>(), Type<T>(), &data[0]);
2534		glBindTexture(GL_TEXTURE_3D, 0);
2535		for (int i = 0; i < kSize * kSize * 2; ++i)
2536		{
2537			if (!tcu::allEqual(data[i], expected_value))
2538			{
2539				status = false;
2540				m_context.getTestContext().getLog()
2541					<< tcu::TestLog::Message << "GL_TEXTURE_3D target failed. Value is: " << ToString(data[i])
2542					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2543				break;
2544			}
2545		}
2546
2547		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2548		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2549		glGetTexImage(GL_TEXTURE_RECTANGLE, 0, Format<T>(), Type<T>(), &data[0]);
2550		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2551		for (int i = 0; i < kSize * kSize; ++i)
2552		{
2553			if (!tcu::allEqual(data[i], expected_value))
2554			{
2555				status = false;
2556				m_context.getTestContext().getLog()
2557					<< tcu::TestLog::Message << "GL_TEXTURE_RECTANGLE target failed. Value is: " << ToString(data[i])
2558					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2559				break;
2560			}
2561		}
2562
2563		{
2564			glBindTexture(GL_TEXTURE_CUBE_MAP, textures[4]);
2565			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2566			for (int face = 0; face < 6; ++face)
2567			{
2568				glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
2569				for (int i = 0; i < kSize * kSize; ++i)
2570				{
2571					if (!tcu::allEqual(data[i], expected_value))
2572					{
2573						status = false;
2574						m_context.getTestContext().getLog()
2575							<< tcu::TestLog::Message
2576							<< "GL_TEXTURE_CUBE_MAP_POSITIVE_X target failed. Value is: " << ToString(data[i])
2577							<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2578						break;
2579					}
2580				}
2581			}
2582			glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
2583		}
2584
2585		glBindTexture(GL_TEXTURE_BUFFER, textures[5]);
2586		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2587		glBindTexture(GL_TEXTURE_BUFFER, 0);
2588		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2589		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, kSize * sizeof(T), &data[0]);
2590		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2591		for (int i = 0; i < kSize; ++i)
2592		{
2593			if (!tcu::allEqual(data[i], expected_value))
2594			{
2595				status = false;
2596				m_context.getTestContext().getLog()
2597					<< tcu::TestLog::Message << "GL_TEXTURE_BUFFER target failed. Value is: " << ToString(data[i])
2598					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2599				break;
2600			}
2601		}
2602
2603		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[6]);
2604		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2605		glGetTexImage(GL_TEXTURE_1D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2606		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2607		for (int i = 0; i < kSize * 2; ++i)
2608		{
2609			if (!tcu::allEqual(data[i], expected_value))
2610			{
2611				status = false;
2612				m_context.getTestContext().getLog()
2613					<< tcu::TestLog::Message << "GL_TEXTURE_1D_ARRAY target failed. Value is: " << ToString(data[i])
2614					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2615				break;
2616			}
2617		}
2618
2619		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[7]);
2620		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2621		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2622		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2623		for (int i = 0; i < kSize * kSize * 2; ++i)
2624		{
2625			if (!tcu::allEqual(data[i], expected_value))
2626			{
2627				status = false;
2628				m_context.getTestContext().getLog()
2629					<< tcu::TestLog::Message << "GL_TEXTURE_2D_ARRAY target failed. Value is: " << ToString(data[i])
2630					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2631				break;
2632			}
2633		}
2634
2635		glUseProgram(0);
2636		glDeleteProgram(program);
2637		glDeleteTextures(8, textures);
2638		glDeleteBuffers(1, &buffer);
2639
2640		return status;
2641	}
2642
2643	template <typename T>
2644	bool WriteMS(GLenum internalformat, const T& write_value, const T& expected_value)
2645	{
2646
2647		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2648							 "  gl_Position = i_position;" NL "}";
2649		const GLuint program	 = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, write_value).c_str());
2650		const GLuint val_program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMSVal(expected_value).c_str());
2651		GLuint		 textures[2];
2652		glGenTextures(2, textures);
2653
2654		const int kSize = 16;
2655
2656		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2657		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
2658		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
2659
2660		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2661		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
2662		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
2663
2664		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
2665		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2666
2667		glClear(GL_COLOR_BUFFER_BIT);
2668		glUseProgram(program);
2669		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
2670		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
2671
2672		glBindVertexArray(m_vao);
2673		glViewport(0, 0, kSize, kSize);
2674		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2675
2676		bool status = true;
2677
2678		glActiveTexture(GL_TEXTURE0);
2679		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
2680		glActiveTexture(GL_TEXTURE1);
2681		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
2682
2683		glUseProgram(val_program);
2684		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms"), 0);
2685		glUniform1i(glGetUniformLocation(val_program, "g_sampler_2dms_array"), 1);
2686
2687		glBindVertexArray(m_vao);
2688		glViewport(0, 0, kSize, kSize);
2689		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
2690		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2691
2692		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
2693		{
2694			status = false;
2695			m_context.getTestContext().getLog()
2696				<< tcu::TestLog::Message
2697				<< "GL_TEXTURE_2D_MULTISAMPLE or GL_TEXTURE_2D_MULTISAMPLE_ARRAY target failed."
2698				<< tcu::TestLog::EndMessage;
2699		}
2700
2701		glActiveTexture(GL_TEXTURE0);
2702		glDeleteTextures(2, textures);
2703		glUseProgram(0);
2704		glDeleteProgram(program);
2705		glDeleteProgram(val_program);
2706
2707		return status;
2708	}
2709
2710	template <typename T>
2711	bool WriteCubeArray(GLenum internalformat, const T& write_value, const T& expected_value)
2712	{
2713		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2714							 "  gl_Position = i_position;" NL "}";
2715		const GLuint program =
2716			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCubeArray(internalformat, write_value).c_str());
2717		GLuint textures[1];
2718		glGenTextures(1, textures);
2719
2720		const int kSize = 16;
2721
2722		std::vector<T> data(kSize * kSize * 12);
2723		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2724		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2725		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
2726					 &data[0]);
2727		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2728
2729		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
2730
2731		glUseProgram(program);
2732		glBindVertexArray(m_vao);
2733		glViewport(0, 0, kSize, kSize);
2734		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2735
2736		bool status = true;
2737
2738		std::fill(data.begin(), data.end(), T(0));
2739		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[0]);
2740		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
2741		glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, Format<T>(), Type<T>(), &data[0]);
2742		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
2743		for (int i = 0; i < kSize * kSize * 12; ++i)
2744		{
2745			if (!tcu::allEqual(data[i], expected_value))
2746			{
2747				status = false;
2748				m_context.getTestContext().getLog()
2749					<< tcu::TestLog::Message
2750					<< "GL_TEXTURE_CUBE_MAP_ARRAY target failed. Value is: " << ToString(data[i])
2751					<< ". Value should be: " << ToString(expected_value) << tcu::TestLog::EndMessage;
2752				break;
2753			}
2754		}
2755
2756		glDeleteTextures(1, textures);
2757		glUseProgram(0);
2758		glDeleteProgram(program);
2759
2760		return status;
2761	}
2762
2763	template <typename T>
2764	std::string GenFS(GLenum internalformat, const T& write_value)
2765	{
2766		std::ostringstream os;
2767		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2768		   << TypePrefix<T>() << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat)
2769		   << ") writeonly uniform " << TypePrefix<T>() << "image2D g_image_2d;" NL "layout("
2770		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2771		   << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2772		   << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat)
2773		   << ") writeonly uniform " << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout("
2774		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
2775		   << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2776		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
2777		   << ") writeonly uniform " << TypePrefix<T>()
2778		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2779			  "  imageStore(g_image_1d, coord.x, "
2780		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2d, coord, " << TypePrefix<T>()
2781		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 0), " << TypePrefix<T>()
2782		   << "vec4" << write_value << ");" NL "  imageStore(g_image_3d, ivec3(coord.xy, 1), " << TypePrefix<T>()
2783		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2drect, coord, " << TypePrefix<T>() << "vec4"
2784		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2785		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2786		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 2), " << TypePrefix<T>() << "vec4"
2787		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 3), " << TypePrefix<T>() << "vec4"
2788		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 4), " << TypePrefix<T>() << "vec4"
2789		   << write_value << ");" NL "  imageStore(g_image_cube, ivec3(coord, 5), " << TypePrefix<T>() << "vec4"
2790		   << write_value << ");" NL "  imageStore(g_image_buffer, coord.x, " << TypePrefix<T>() << "vec4"
2791		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 0), " << TypePrefix<T>() << "vec4"
2792		   << write_value << ");" NL "  imageStore(g_image_1darray, ivec2(coord.x, 1), " << TypePrefix<T>() << "vec4"
2793		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 0), " << TypePrefix<T>() << "vec4"
2794		   << write_value << ");" NL "  imageStore(g_image_2darray, ivec3(coord, 1), " << TypePrefix<T>() << "vec4"
2795		   << write_value << ");" NL "  discard;" NL "}";
2796		return os.str();
2797	}
2798
2799	template <typename T>
2800	std::string GenFSMS(GLenum internalformat, const T& write_value)
2801	{
2802		std::ostringstream os;
2803		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2804		   << TypePrefix<T>() << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat)
2805		   << ") writeonly uniform " << TypePrefix<T>()
2806		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2807			  "  imageStore(g_image_2dms, coord, 0, "
2808		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 1, "
2809		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 2, "
2810		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms, coord, 3, "
2811		   << TypePrefix<T>() << "vec4" << write_value
2812		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 0, " << TypePrefix<T>() << "vec4"
2813		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 1, " << TypePrefix<T>()
2814		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 2, "
2815		   << TypePrefix<T>() << "vec4" << write_value
2816		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 0), 3, " << TypePrefix<T>() << "vec4"
2817		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 0, " << TypePrefix<T>()
2818		   << "vec4" << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 1, "
2819		   << TypePrefix<T>() << "vec4" << write_value
2820		   << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 2, " << TypePrefix<T>() << "vec4"
2821		   << write_value << ");" NL "  imageStore(g_image_2dms_array, ivec3(coord, 1), 3, " << TypePrefix<T>()
2822		   << "vec4" << write_value << ");" NL "  discard;" NL "}";
2823		return os.str();
2824	}
2825
2826	template <typename T>
2827	std::string GenFSMSVal(const T& expected_value)
2828	{
2829		std::ostringstream os;
2830		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform " << TypePrefix<T>()
2831		   << "sampler2DMS g_sampler_2dms;" NL "uniform " << TypePrefix<T>()
2832		   << "sampler2DMSArray g_sampler_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
2833			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (texelFetch(g_sampler_2dms, coord, 0) != "
2834		   << TypePrefix<T>() << "vec4" << expected_value
2835		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 1) != "
2836		   << TypePrefix<T>() << "vec4" << expected_value
2837		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 2) != "
2838		   << TypePrefix<T>() << "vec4" << expected_value
2839		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (texelFetch(g_sampler_2dms, coord, 3) != "
2840		   << TypePrefix<T>() << "vec4" << expected_value
2841		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
2842			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 0) != "
2843		   << TypePrefix<T>() << "vec4" << expected_value
2844		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2845			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 1) != "
2846		   << TypePrefix<T>() << "vec4" << expected_value
2847		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2848			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 2) != "
2849		   << TypePrefix<T>() << "vec4" << expected_value
2850		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2851			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 0), 3) != "
2852		   << TypePrefix<T>() << "vec4" << expected_value
2853		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL
2854			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 0) != "
2855		   << TypePrefix<T>() << "vec4" << expected_value
2856		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2857			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 1) != "
2858		   << TypePrefix<T>() << "vec4" << expected_value
2859		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2860			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 2) != "
2861		   << TypePrefix<T>() << "vec4" << expected_value
2862		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
2863			  "  if (texelFetch(g_sampler_2dms_array, ivec3(coord, 1), 3) != "
2864		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
2865		return os.str();
2866	}
2867
2868	template <typename T>
2869	std::string GenFSCubeArray(GLenum internalformat, const T& write_value)
2870	{
2871		std::ostringstream os;
2872		os << "#version 420 core" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
2873		   << TypePrefix<T>()
2874		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
2875			  "  imageStore(g_image_cube_array, ivec3(coord, 0), "
2876		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 1), "
2877		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 2), "
2878		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 3), "
2879		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 4), "
2880		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 5), "
2881		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 6), "
2882		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 7), "
2883		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 8), "
2884		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 9), "
2885		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 10), "
2886		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  imageStore(g_image_cube_array, ivec3(coord, 11), "
2887		   << TypePrefix<T>() << "vec4" << write_value << ");" NL "  discard;" NL "}";
2888		return os.str();
2889	}
2890};
2891//-----------------------------------------------------------------------------
2892// 1.3.2.1 BasicAllTargetsLoadNonMS
2893//-----------------------------------------------------------------------------
2894class BasicAllTargetsLoadNonMS : public ShaderImageLoadStoreBase
2895{
2896	GLuint m_vao;
2897	GLuint m_vbo;
2898
2899	virtual long Setup()
2900	{
2901		m_vao = 0;
2902		m_vbo = 0;
2903		return NO_ERROR;
2904	}
2905
2906	virtual long Run()
2907	{
2908		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
2909
2910		if (!Read(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2911			return ERROR;
2912		if (!Read(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2913			return ERROR;
2914		if (!Read(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2915			return ERROR;
2916
2917		if (!ReadCube(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
2918			return ERROR;
2919		if (!ReadCube(GL_RGBA32I, ivec4(-1, 10, -200, 3000), ivec4(-1, 10, -200, 3000)))
2920			return ERROR;
2921		if (!ReadCube(GL_RGBA32UI, uvec4(1, 10, 200, 3000), uvec4(1, 10, 200, 3000)))
2922			return ERROR;
2923
2924		return NO_ERROR;
2925	}
2926
2927	virtual long Cleanup()
2928	{
2929		glViewport(0, 0, getWindowWidth(), getWindowHeight());
2930		glDeleteVertexArrays(1, &m_vao);
2931		glDeleteBuffers(1, &m_vbo);
2932		return NO_ERROR;
2933	}
2934
2935	template <typename T>
2936	bool Read(GLenum internalformat, const T& value, const T& expected_value)
2937	{
2938		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
2939							 "  gl_Position = i_position;" NL "}";
2940		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS(internalformat, expected_value).c_str());
2941		GLuint		 textures[7];
2942		GLuint		 buffer;
2943		glGenTextures(7, textures);
2944		glGenBuffers(1, &buffer);
2945
2946		const int	  kSize = 16;
2947		std::vector<T> data(kSize * kSize * 2, value);
2948
2949		glBindTexture(GL_TEXTURE_1D, textures[0]);
2950		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2951		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2952		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2953		glBindTexture(GL_TEXTURE_1D, 0);
2954
2955		glBindTexture(GL_TEXTURE_2D, textures[1]);
2956		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2957		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2958		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2959		glBindTexture(GL_TEXTURE_2D, 0);
2960
2961		glBindTexture(GL_TEXTURE_3D, textures[2]);
2962		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2963		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2964		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2965		glBindTexture(GL_TEXTURE_3D, 0);
2966
2967		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
2968		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2969		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2970		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
2971		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
2972
2973		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
2974		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
2975		glBindBuffer(GL_TEXTURE_BUFFER, 0);
2976		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
2977		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
2978		glBindTexture(GL_TEXTURE_BUFFER, 0);
2979
2980		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
2981		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2982		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2983		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2984		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
2985
2986		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
2987		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2988		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2989		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
2990		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
2991
2992		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2993		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2994		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2995		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2996		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
2997		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2998		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
2999
3000		glClear(GL_COLOR_BUFFER_BIT);
3001
3002		glUseProgram(program);
3003		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3004		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3005		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3006		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3007		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3008		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3009		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3010
3011		glBindVertexArray(m_vao);
3012		glViewport(0, 0, kSize, kSize);
3013		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3014
3015		bool status = true;
3016
3017		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3018		{
3019			status = false;
3020		}
3021
3022		std::map<std::string, GLuint> name_index_map;
3023		GLint uniforms;
3024		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3025		if (uniforms != 7)
3026		{
3027			status = false;
3028			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3029												<< " should be 7." << tcu::TestLog::EndMessage;
3030		}
3031		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3032		{
3033			GLchar name[32];
3034			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3035			name_index_map.insert(std::make_pair(std::string(name), index));
3036		}
3037
3038		if (!CheckUniform(program, "g_image_1d", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D)))
3039			status = false;
3040		if (!CheckUniform(program, "g_image_2d", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D)))
3041			status = false;
3042		if (!CheckUniform(program, "g_image_3d", name_index_map, 1, ImageType<T>(GL_TEXTURE_3D)))
3043			status = false;
3044		if (!CheckUniform(program, "g_image_2drect", name_index_map, 1, ImageType<T>(GL_TEXTURE_RECTANGLE)))
3045			status = false;
3046		if (!CheckUniform(program, "g_image_buffer", name_index_map, 1, ImageType<T>(GL_TEXTURE_BUFFER)))
3047			status = false;
3048		if (!CheckUniform(program, "g_image_1darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_1D_ARRAY)))
3049			status = false;
3050		if (!CheckUniform(program, "g_image_2darray", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_ARRAY)))
3051			status = false;
3052
3053		glUseProgram(0);
3054		glDeleteProgram(program);
3055		glDeleteTextures(7, textures);
3056		glDeleteBuffers(1, &buffer);
3057
3058		return status;
3059	}
3060
3061	template <typename T>
3062	bool ReadCube(GLenum internalformat, const T& value, const T& expected_value)
3063	{
3064		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3065							 "  gl_Position = i_position;" NL "}";
3066		const GLuint program =
3067			BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube(internalformat, expected_value).c_str());
3068		GLuint textures[2];
3069		glGenTextures(2, textures);
3070
3071		const int	  kSize = 16;
3072		std::vector<T> data(kSize * kSize * 12, value);
3073
3074		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3075		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3076		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3077		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3078					 &data[0]);
3079		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3080					 &data[0]);
3081		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3082					 &data[0]);
3083		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3084					 &data[0]);
3085		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3086					 &data[0]);
3087		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3088					 &data[0]);
3089		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3090
3091		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3092		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3093		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3094		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3095					 &data[0]);
3096		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3097
3098		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3099		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3100
3101		glClear(GL_COLOR_BUFFER_BIT);
3102
3103		glUseProgram(program);
3104		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3105		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3106
3107		glBindVertexArray(m_vao);
3108		glViewport(0, 0, kSize, kSize);
3109		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3110
3111		bool status = true;
3112
3113		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3114		{
3115			status = false;
3116		}
3117
3118		std::map<std::string, GLuint> name_index_map;
3119		GLint uniforms;
3120		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3121		if (uniforms != 2)
3122		{
3123			status = false;
3124			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3125												<< " should be 2." << tcu::TestLog::EndMessage;
3126		}
3127		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3128		{
3129			GLchar name[32];
3130			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3131			name_index_map.insert(std::make_pair(std::string(name), index));
3132		}
3133
3134		if (!CheckUniform(program, "g_image_cube", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP)))
3135			status = false;
3136		if (!CheckUniform(program, "g_image_cube_array", name_index_map, 1, ImageType<T>(GL_TEXTURE_CUBE_MAP_ARRAY)))
3137			status = false;
3138
3139		glUseProgram(0);
3140		glDeleteProgram(program);
3141		glDeleteTextures(2, textures);
3142
3143		return status;
3144	}
3145
3146	template <typename T>
3147	std::string GenFS(GLenum internalformat, const T& expected_value)
3148	{
3149		std::ostringstream os;
3150		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3151		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3152		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3153		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3154		   << ") readonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3155		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3156		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3157		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3158		   << ") readonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3159		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3160		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3161			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3162		   << TypePrefix<T>()
3163		   << "vec4 v;" NL "  v = imageLoad(g_image_1d, coord.x);" NL "  if (v != " << TypePrefix<T>() << "vec4"
3164		   << expected_value
3165		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_2d, coord);" NL "  if (v != "
3166		   << TypePrefix<T>() << "vec4" << expected_value
3167		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 0));" NL
3168			  "  if (v != "
3169		   << TypePrefix<T>() << "vec4" << expected_value
3170		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_3d, ivec3(coord.xy, 1));" NL
3171			  "  if (v != "
3172		   << TypePrefix<T>() << "vec4" << expected_value
3173		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_2drect, coord);" NL "  if (v != "
3174		   << TypePrefix<T>() << "vec4" << expected_value
3175		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_buffer, coord.x);" NL "  if (v != "
3176		   << TypePrefix<T>() << "vec4" << expected_value
3177		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 0));" NL
3178			  "  if (v != "
3179		   << TypePrefix<T>() << "vec4" << expected_value
3180		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.65);" NL "  v = imageLoad(g_image_1darray, ivec2(coord.x, 1));" NL
3181			  "  if (v != "
3182		   << TypePrefix<T>() << "vec4" << expected_value
3183		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 0));" NL
3184			  "  if (v != "
3185		   << TypePrefix<T>() << "vec4" << expected_value
3186		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.75);" NL "  v = imageLoad(g_image_2darray, ivec3(coord, 1));" NL
3187			  "  if (v != "
3188		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL "}";
3189		return os.str();
3190	}
3191
3192	template <typename T>
3193	std::string GenFSCube(GLenum internalformat, const T& expected_value)
3194	{
3195		std::ostringstream os;
3196		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3197		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3198		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3199		   << TypePrefix<T>()
3200		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3201			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  "
3202		   << TypePrefix<T>()
3203		   << "vec4 v;" NL "  v = imageLoad(g_image_cube, ivec3(coord, 0));" NL "  if (v != " << TypePrefix<T>()
3204		   << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
3205										  "  v = imageLoad(g_image_cube, ivec3(coord, 1));" NL "  if (v != "
3206		   << TypePrefix<T>() << "vec4" << expected_value
3207		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 2));" NL
3208			  "  if (v != "
3209		   << TypePrefix<T>() << "vec4" << expected_value
3210		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 3));" NL
3211			  "  if (v != "
3212		   << TypePrefix<T>() << "vec4" << expected_value
3213		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 4));" NL
3214			  "  if (v != "
3215		   << TypePrefix<T>() << "vec4" << expected_value
3216		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube, ivec3(coord, 5));" NL
3217			  "  if (v != "
3218		   << TypePrefix<T>() << "vec4" << expected_value
3219		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 0));" NL
3220			  "  if (v != "
3221		   << TypePrefix<T>() << "vec4" << expected_value
3222		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.05);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 1));" NL
3223			  "  if (v != "
3224		   << TypePrefix<T>() << "vec4" << expected_value
3225		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 2));" NL
3226			  "  if (v != "
3227		   << TypePrefix<T>() << "vec4" << expected_value
3228		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.15);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 3));" NL
3229			  "  if (v != "
3230		   << TypePrefix<T>() << "vec4" << expected_value
3231		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 4));" NL
3232			  "  if (v != "
3233		   << TypePrefix<T>() << "vec4" << expected_value
3234		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.25);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 5));" NL
3235			  "  if (v != "
3236		   << TypePrefix<T>() << "vec4" << expected_value
3237		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 6));" NL
3238			  "  if (v != "
3239		   << TypePrefix<T>() << "vec4" << expected_value
3240		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.35);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 7));" NL
3241			  "  if (v != "
3242		   << TypePrefix<T>() << "vec4" << expected_value
3243		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 8));" NL
3244			  "  if (v != "
3245		   << TypePrefix<T>() << "vec4" << expected_value
3246		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.45);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 9));" NL
3247			  "  if (v != "
3248		   << TypePrefix<T>() << "vec4" << expected_value
3249		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.5);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 10));" NL
3250			  "  if (v != "
3251		   << TypePrefix<T>() << "vec4" << expected_value
3252		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.55);" NL "  v = imageLoad(g_image_cube_array, ivec3(coord, 11));" NL
3253			  "  if (v != "
3254		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.6);" NL "}";
3255		return os.str();
3256	}
3257};
3258//-----------------------------------------------------------------------------
3259// 1.3.2.2 BasicAllTargetsLoadMS
3260//-----------------------------------------------------------------------------
3261class BasicAllTargetsLoadMS : public ShaderImageLoadStoreBase
3262{
3263	GLuint m_vao;
3264	GLuint m_vbo;
3265
3266	virtual long Setup()
3267	{
3268		m_vao = 0;
3269		m_vbo = 0;
3270		return NO_ERROR;
3271	}
3272
3273	virtual long Run()
3274	{
3275		if (!SupportedSamples(4))
3276			return NOT_SUPPORTED;
3277
3278		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3279
3280		if (!ReadMS(GL_RGBA32F, vec4(-1.0f, 10.0f, -200.0f, 3000.0f), vec4(-1.0f, 10.0f, -200.0f, 3000.0f)))
3281			return ERROR;
3282
3283		GLint isamples;
3284		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3285		if (isamples >= 4)
3286		{
3287			if (!ReadMS(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
3288				return ERROR;
3289			if (!ReadMS(GL_RGBA32UI, uvec4(1, 2, 3, 4), uvec4(1, 2, 3, 4)))
3290				return ERROR;
3291		}
3292
3293		return NO_ERROR;
3294	}
3295
3296	virtual long Cleanup()
3297	{
3298		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3299		glDeleteVertexArrays(1, &m_vao);
3300		glDeleteBuffers(1, &m_vbo);
3301		return NO_ERROR;
3302	}
3303
3304	template <typename T>
3305	bool ReadMS(GLenum internalformat, const T& value, const T& expected_value)
3306	{
3307		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3308							 "  gl_Position = i_position;" NL "}";
3309		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS(internalformat, expected_value).c_str());
3310		GLuint		 textures[2];
3311		glGenTextures(2, textures);
3312
3313		const int kSize = 16;
3314
3315		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3316		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3317		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3318
3319		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3320		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3321		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3322
3323		GLuint fbo;
3324		glGenFramebuffers(1, &fbo);
3325		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3326		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3327		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3328		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3329		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3330		glDrawBuffers(3, draw_buffers);
3331		ClearBuffer(GL_COLOR, 0, value);
3332		ClearBuffer(GL_COLOR, 1, value);
3333		ClearBuffer(GL_COLOR, 2, value);
3334		glDeleteFramebuffers(1, &fbo);
3335
3336		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
3337		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
3338
3339		glUseProgram(program);
3340		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3341		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3342
3343		glClear(GL_COLOR_BUFFER_BIT);
3344		glBindVertexArray(m_vao);
3345		glViewport(0, 0, kSize, kSize);
3346		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3347
3348		bool status = true;
3349
3350		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3351		{
3352			status = false;
3353		}
3354
3355		std::map<std::string, GLuint> name_index_map;
3356		GLint uniforms;
3357		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniforms);
3358		if (uniforms != 2)
3359		{
3360			status = false;
3361			m_context.getTestContext().getLog() << tcu::TestLog::Message << "ACTIVE_UNIFORMS is " << uniforms
3362												<< " should be 2." << tcu::TestLog::EndMessage;
3363		}
3364		for (GLuint index = 0; index < static_cast<GLuint>(uniforms); ++index)
3365		{
3366			GLchar name[32];
3367			glGetActiveUniformName(program, index, sizeof(name), NULL, name);
3368			name_index_map.insert(std::make_pair(std::string(name), index));
3369		}
3370
3371		if (!CheckUniform(program, "g_image_2dms", name_index_map, 1, ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE)))
3372			status = false;
3373		if (!CheckUniform(program, "g_image_2dms_array", name_index_map, 1,
3374						  ImageType<T>(GL_TEXTURE_2D_MULTISAMPLE_ARRAY)))
3375			status = false;
3376
3377		glDeleteTextures(2, textures);
3378		glUseProgram(0);
3379		glDeleteProgram(program);
3380
3381		return status;
3382	}
3383
3384	template <typename T>
3385	std::string GenFSMS(GLenum internalformat, const T& expected_value)
3386	{
3387		std::ostringstream os;
3388		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3389		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
3390		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
3391		   << TypePrefix<T>()
3392		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3393			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  if (imageLoad(g_image_2dms, coord, 0) != "
3394		   << TypePrefix<T>() << "vec4" << expected_value
3395		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 1) != "
3396		   << TypePrefix<T>() << "vec4" << expected_value
3397		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 2) != "
3398		   << TypePrefix<T>() << "vec4" << expected_value
3399		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms, coord, 3) != "
3400		   << TypePrefix<T>() << "vec4" << expected_value
3401		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 0) != "
3402		   << TypePrefix<T>() << "vec4" << expected_value
3403		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 1) != "
3404		   << TypePrefix<T>() << "vec4" << expected_value
3405		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 2) != "
3406		   << TypePrefix<T>() << "vec4" << expected_value
3407		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 0), 3) != "
3408		   << TypePrefix<T>() << "vec4" << expected_value
3409		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 0) != "
3410		   << TypePrefix<T>() << "vec4" << expected_value
3411		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 1) != "
3412		   << TypePrefix<T>() << "vec4" << expected_value
3413		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 2) != "
3414		   << TypePrefix<T>() << "vec4" << expected_value
3415		   << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "  if (imageLoad(g_image_2dms_array, ivec3(coord, 1), 3) != "
3416		   << TypePrefix<T>() << "vec4" << expected_value << ") o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL "}";
3417		return os.str();
3418	}
3419};
3420//-----------------------------------------------------------------------------
3421// 1.3.3 BasicAllTargetsAtomic
3422//-----------------------------------------------------------------------------
3423class BasicAllTargetsAtomic : public ShaderImageLoadStoreBase
3424{
3425	GLuint m_vao;
3426	GLuint m_vbo;
3427
3428	virtual long Setup()
3429	{
3430		m_vao = 0;
3431		m_vbo = 0;
3432		return NO_ERROR;
3433	}
3434
3435	virtual long Run()
3436	{
3437		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
3438
3439		if (!Atomic<GLint>(GL_R32I))
3440			return ERROR;
3441		if (!Atomic<GLuint>(GL_R32UI))
3442			return ERROR;
3443
3444		if (!AtomicCube<GLint>(GL_R32I))
3445			return ERROR;
3446		if (!AtomicCube<GLuint>(GL_R32UI))
3447			return ERROR;
3448
3449		GLint isamples;
3450		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &isamples);
3451		if (SupportedSamples(4) && isamples >= 4)
3452		{
3453			if (!AtomicMS<GLint>(GL_R32I))
3454				return ERROR;
3455			if (!AtomicMS<GLuint>(GL_R32UI))
3456				return ERROR;
3457		}
3458
3459		return NO_ERROR;
3460	}
3461
3462	virtual long Cleanup()
3463	{
3464		glViewport(0, 0, getWindowWidth(), getWindowHeight());
3465		glDeleteVertexArrays(1, &m_vao);
3466		glDeleteBuffers(1, &m_vbo);
3467		return NO_ERROR;
3468	}
3469
3470	template <typename T>
3471	bool Atomic(GLenum internalformat)
3472	{
3473		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3474							 "  gl_Position = i_position;" NL "}";
3475		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFS<T>(internalformat).c_str());
3476		GLuint		 textures[7];
3477		GLuint		 buffer;
3478		glGenTextures(7, textures);
3479		glGenBuffers(1, &buffer);
3480
3481		const int	  kSize = 16;
3482		std::vector<T> data(kSize * kSize * 2);
3483
3484		glBindTexture(GL_TEXTURE_1D, textures[0]);
3485		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3486		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3487		glTexImage1D(GL_TEXTURE_1D, 0, internalformat, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3488		glBindTexture(GL_TEXTURE_1D, 0);
3489
3490		glBindTexture(GL_TEXTURE_2D, textures[1]);
3491		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3492		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3493		glTexImage2D(GL_TEXTURE_2D, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3494		glBindTexture(GL_TEXTURE_2D, 0);
3495
3496		glBindTexture(GL_TEXTURE_3D, textures[2]);
3497		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3498		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3499		glTexImage3D(GL_TEXTURE_3D, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3500		glBindTexture(GL_TEXTURE_3D, 0);
3501
3502		glBindTexture(GL_TEXTURE_RECTANGLE, textures[3]);
3503		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3504		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3505		glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(), &data[0]);
3506		glBindTexture(GL_TEXTURE_RECTANGLE, 0);
3507
3508		glBindBuffer(GL_TEXTURE_BUFFER, buffer);
3509		glBufferData(GL_TEXTURE_BUFFER, kSize * sizeof(T), &data[0], GL_DYNAMIC_DRAW);
3510		glBindBuffer(GL_TEXTURE_BUFFER, 0);
3511		glBindTexture(GL_TEXTURE_BUFFER, textures[4]);
3512		glTexBuffer(GL_TEXTURE_BUFFER, internalformat, buffer);
3513		glBindTexture(GL_TEXTURE_BUFFER, 0);
3514
3515		glBindTexture(GL_TEXTURE_1D_ARRAY, textures[5]);
3516		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3517		glTexParameteri(GL_TEXTURE_1D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3518		glTexImage2D(GL_TEXTURE_1D_ARRAY, 0, internalformat, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3519		glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
3520
3521		glBindTexture(GL_TEXTURE_2D_ARRAY, textures[6]);
3522		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3523		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3524		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internalformat, kSize, kSize, 2, 0, Format<T>(), Type<T>(), &data[0]);
3525		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
3526
3527		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3528		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3529		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3530		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3531		glBindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3532		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3533		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3534
3535		glClear(GL_COLOR_BUFFER_BIT);
3536
3537		glUseProgram(program);
3538		glUniform1i(glGetUniformLocation(program, "g_image_1d"), 0);
3539		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
3540		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
3541		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
3542		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 4);
3543		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 5);
3544		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 6);
3545
3546		glBindVertexArray(m_vao);
3547		glViewport(0, 0, kSize, 1);
3548		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3549
3550		bool status = true;
3551
3552		if (!ValidateReadBuffer(0, 0, kSize, 1, vec4(0, 1, 0, 1)))
3553		{
3554			status = false;
3555		}
3556
3557		glUseProgram(0);
3558		glDeleteProgram(program);
3559		glDeleteTextures(7, textures);
3560		glDeleteBuffers(1, &buffer);
3561
3562		return status;
3563	}
3564
3565	template <typename T>
3566	bool AtomicCube(GLenum internalformat)
3567	{
3568		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3569							 "  gl_Position = i_position;" NL "}";
3570		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSCube<T>(internalformat).c_str());
3571		GLuint		 textures[2];
3572		glGenTextures(2, textures);
3573
3574		const int	  kSize = 16;
3575		std::vector<T> data(kSize * kSize * 12);
3576
3577		glBindTexture(GL_TEXTURE_CUBE_MAP, textures[0]);
3578		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3579		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3580		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3581					 &data[0]);
3582		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3583					 &data[0]);
3584		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3585					 &data[0]);
3586		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3587					 &data[0]);
3588		glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3589					 &data[0]);
3590		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, kSize, kSize, 0, Format<T>(), Type<T>(),
3591					 &data[0]);
3592		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
3593
3594		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, textures[1]);
3595		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3596		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3597		glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, internalformat, kSize, kSize, 12, 0, Format<T>(), Type<T>(),
3598					 &data[0]);
3599		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
3600
3601		glBindImageTexture(0, textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3602		glBindImageTexture(1, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3603
3604		glClear(GL_COLOR_BUFFER_BIT);
3605
3606		glUseProgram(program);
3607		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 0);
3608		glUniform1i(glGetUniformLocation(program, "g_image_cube_array"), 1);
3609
3610		glBindVertexArray(m_vao);
3611		glViewport(0, 0, kSize, kSize);
3612		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3613
3614		bool status = true;
3615
3616		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3617		{
3618			status = false;
3619		}
3620
3621		glUseProgram(0);
3622		glDeleteProgram(program);
3623		glDeleteTextures(2, textures);
3624
3625		return status;
3626	}
3627
3628	template <typename T>
3629	bool AtomicMS(GLenum internalformat)
3630	{
3631		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
3632							 "  gl_Position = i_position;" NL "}";
3633		const GLuint program = BuildProgram(src_vs, NULL, NULL, NULL, GenFSMS<T>(internalformat).c_str());
3634		GLuint		 textures[2];
3635		glGenTextures(2, textures);
3636
3637		const int kSize = 16;
3638
3639		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, textures[0]);
3640		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, internalformat, kSize, kSize, GL_FALSE);
3641		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
3642
3643		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, textures[1]);
3644		glTexImage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 4, internalformat, kSize, kSize, 2, GL_FALSE);
3645		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, 0);
3646
3647		GLuint fbo;
3648		glGenFramebuffers(1, &fbo);
3649		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3650		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textures[0], 0);
3651		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, textures[1], 0, 0);
3652		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, textures[1], 0, 1);
3653		const GLenum draw_buffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
3654		glDrawBuffers(3, draw_buffers);
3655		if (internalformat == GL_R32I)
3656		{
3657			const GLint value[4] = { 0, 0, 0, 0 };
3658			glClearBufferiv(GL_COLOR, 0, value);
3659			glClearBufferiv(GL_COLOR, 1, value);
3660			glClearBufferiv(GL_COLOR, 2, value);
3661		}
3662		else
3663		{
3664			const GLuint value[4] = { 0, 0, 0, 0 };
3665			glClearBufferuiv(GL_COLOR, 0, value);
3666			glClearBufferuiv(GL_COLOR, 1, value);
3667			glClearBufferuiv(GL_COLOR, 2, value);
3668		}
3669		glDeleteFramebuffers(1, &fbo);
3670
3671		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
3672		glBindImageTexture(4, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
3673
3674		glUseProgram(program);
3675		glUniform1i(glGetUniformLocation(program, "g_image_2dms"), 1);
3676		glUniform1i(glGetUniformLocation(program, "g_image_2dms_array"), 4);
3677
3678		glClear(GL_COLOR_BUFFER_BIT);
3679		glBindVertexArray(m_vao);
3680		glViewport(0, 0, kSize, kSize);
3681		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3682
3683		bool status = true;
3684
3685		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
3686		{
3687			status = false;
3688		}
3689
3690		glDeleteTextures(2, textures);
3691		glUseProgram(0);
3692		glDeleteProgram(program);
3693
3694		return status;
3695	}
3696
3697	template <typename T>
3698	std::string GenFS(GLenum internalformat)
3699	{
3700		std::ostringstream os;
3701		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3702		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3703		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3704		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
3705		   << ") coherent uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
3706		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3707		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3708		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
3709		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
3710		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3711		   << "image2DArray g_image_2darray;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3712			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3713
3714			NL "  if (imageAtomicAdd(g_image_1d, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3715			  "  if (imageAtomicMin(g_image_1d, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3716			  "  if (imageAtomicMax(g_image_1d, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3717			  "  if (imageAtomicAnd(g_image_1d, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3718			  "  if (imageAtomicOr(g_image_1d, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3719			  "  if (imageAtomicXor(g_image_1d, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3720			  "  if (imageAtomicExchange(g_image_1d, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3721			  "  if (imageAtomicCompSwap(g_image_1d, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3722			  "  if (imageAtomicExchange(g_image_1d, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3723
3724			NL "  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3725			  "  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3726			  "  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3727			  "  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3728			  "  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3729			  "  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3730			  "  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3731			  "  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3732			  "  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3733
3734			NL "  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3735			  "  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3736			  "  if (imageAtomicMax(g_image_3d, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3737			  "  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3738			  "  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3739			  "  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3740			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3741			  "  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3742			  "1.0);" NL
3743			  "  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3744
3745			NL "  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3746			  "  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3747			  "  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3748			  "  if (imageAtomicAnd(g_image_2drect, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3749			  "  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3750			  "  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3751			  "  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3752			  "  if (imageAtomicCompSwap(g_image_2drect, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3753			  "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3754
3755			NL "  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3756			  "  if (imageAtomicMin(g_image_buffer, coord.x, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3757			  "  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3758			  "  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3759			  "  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3760			  "  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3761			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3762			  "  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3763			  "  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3764
3765			NL
3766			  "  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3767			  "  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3768			  "  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3769			  "  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3770			  "  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3771			  "  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3772			  "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3773			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = "
3774			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), "
3775			  "0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3776
3777			NL "  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3778			  "  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3779			  "  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3780			  "  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3781			  "  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3782			  "  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3783			  "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
3784			  "1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, "
3785			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) "
3786			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
3787		return os.str();
3788	}
3789
3790	template <typename T>
3791	std::string GenFSCube(GLenum internalformat)
3792	{
3793		std::ostringstream os;
3794		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3795		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3796		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3797		   << TypePrefix<T>()
3798		   << "imageCubeArray g_image_cube_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3799			  "  ivec2 coord = ivec2(gl_FragCoord.xy);"
3800
3801			NL "  if (imageAtomicAdd(g_image_cube, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3802			  "  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3803			  "  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3804			  "  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3805			  "  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3806			  "  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3807			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3808			  "  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
3809			  "1.0);" NL
3810			  "  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
3811
3812			NL "  if (imageAtomicAdd(g_image_cube_array, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3813			  "1.0);" NL "  if (imageAtomicMin(g_image_cube_array, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, "
3814			  "0.0, 1.0);" NL "  if (imageAtomicMax(g_image_cube_array, ivec3(coord, 0), 4) != 2) o_color "
3815			  "= vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicAnd(g_image_cube_array, "
3816			  "ivec3(coord, 0), 0) != 4) o_color = "
3817			  "vec4(1.0, 0.0, 0.0, 1.0);" NL
3818			  "  if (imageAtomicOr(g_image_cube_array, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3819			  "  if (imageAtomicXor(g_image_cube_array, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, "
3820			  "1.0);" NL "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, "
3821			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_cube_array, ivec3(coord, 0), 1, 6) != "
3822			  "1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3823			  "  if (imageAtomicExchange(g_image_cube_array, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, "
3824			  "1.0);" NL "}";
3825		return os.str();
3826	}
3827
3828	template <typename T>
3829	std::string GenFSMS(GLenum internalformat)
3830	{
3831		std::ostringstream os;
3832		os << "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "layout("
3833		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
3834		   << "image2DMS g_image_2dms;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
3835		   << TypePrefix<T>()
3836		   << "image2DMSArray g_image_2dms_array;" NL "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
3837			  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
3838			  "  if (imageAtomicAdd(g_image_2dms, coord, 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3839			  "  if (imageAtomicMin(g_image_2dms, coord, 1, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3840			  "  if (imageAtomicMax(g_image_2dms, coord, 1, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3841			  "  if (imageAtomicAnd(g_image_2dms, coord, 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3842			  "  if (imageAtomicOr(g_image_2dms, coord, 1, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3843			  "  if (imageAtomicXor(g_image_2dms, coord, 1, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3844			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3845			  "  if (imageAtomicCompSwap(g_image_2dms, coord, 1, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3846			  "  if (imageAtomicExchange(g_image_2dms, coord, 1, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL NL
3847			  "  if (imageAtomicAdd(g_image_2dms_array, ivec3(coord, 1), 1, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, "
3848			  "1.0);" NL "  if (imageAtomicMin(g_image_2dms_array, ivec3(coord, 1), 1, 3) != 2) o_color = vec4(1.0, "
3849			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicMax(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 2) "
3850			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3851			  "  if (imageAtomicAnd(g_image_2dms_array, ivec3(coord, 1), 1, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, "
3852			  "1.0);" NL "  if (imageAtomicOr(g_image_2dms_array, ivec3(coord, 1), 1, 7) != 0) o_color = vec4(1.0, "
3853			  "0.0, 0.0, 1.0);" NL "  if (imageAtomicXor(g_image_2dms_array, ivec3(coord, 1), 1, 4) != 7) "
3854			  "o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
3855			  "  if (imageAtomicExchange(g_image_2dms_array, ivec3(coord, 1), 1, 1) != 3) o_color = vec4(1.0, 0.0, "
3856			  "0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2dms_array, ivec3(coord, 1), 1, 1, 6) != 1) o_color = "
3857			  "vec4(1.0, 0.0, 0.0, 1.0);" NL "  if (imageAtomicExchange(g_image_2dms_array, "
3858			  "ivec3(coord, 1), 1, 0) != 6) o_color = vec4(1.0, 0.0, "
3859			  "0.0, 1.0);" NL "}";
3860		return os.str();
3861	}
3862};
3863//-----------------------------------------------------------------------------
3864// LoadStoreMachine
3865//-----------------------------------------------------------------------------
3866class LoadStoreMachine : public ShaderImageLoadStoreBase
3867{
3868	GLuint m_vao;
3869	int	m_stage;
3870
3871	virtual long Setup()
3872	{
3873		glGenVertexArrays(1, &m_vao);
3874		return NO_ERROR;
3875	}
3876
3877	virtual long Cleanup()
3878	{
3879		glDisable(GL_RASTERIZER_DISCARD);
3880		glDeleteVertexArrays(1, &m_vao);
3881		return NO_ERROR;
3882	}
3883
3884	template <typename T>
3885	bool Write(GLenum internalformat, const T& write_value, const T& expected_value)
3886	{
3887		const GLenum targets[] = { GL_TEXTURE_1D,		GL_TEXTURE_2D,
3888								   GL_TEXTURE_3D,		GL_TEXTURE_RECTANGLE,
3889								   GL_TEXTURE_CUBE_MAP, GL_TEXTURE_1D_ARRAY,
3890								   GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY };
3891		const int kTargets		= sizeof(targets) / sizeof(targets[0]);
3892		GLuint	program_store = 0;
3893		GLuint	program_load  = 0;
3894		if (m_stage == 0)
3895		{ // VS
3896			program_store =
3897				BuildProgram(GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL, NULL, NULL);
3898			program_load =
3899				BuildProgram(GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL, NULL, NULL);
3900		}
3901		else if (m_stage == 1)
3902		{ // TCS
3903			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
3904			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
3905			program_store = BuildProgram(glsl_vs, GenStoreShader(m_stage, internalformat, write_value).c_str(),
3906										 glsl_tes, NULL, NULL);
3907			program_load = BuildProgram(glsl_vs, GenLoadShader(m_stage, internalformat, expected_value).c_str(),
3908										glsl_tes, NULL, NULL);
3909		}
3910		else if (m_stage == 2)
3911		{ // TES
3912			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3913			program_store =
3914				BuildProgram(glsl_vs, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL, NULL);
3915			program_load =
3916				BuildProgram(glsl_vs, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL, NULL);
3917		}
3918		else if (m_stage == 3)
3919		{ // GS
3920			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
3921			program_store =
3922				BuildProgram(glsl_vs, NULL, NULL, GenStoreShader(m_stage, internalformat, write_value).c_str(), NULL);
3923			program_load =
3924				BuildProgram(glsl_vs, NULL, NULL, GenLoadShader(m_stage, internalformat, expected_value).c_str(), NULL);
3925		}
3926		else if (m_stage == 4)
3927		{ // CS
3928			{
3929				std::string		  source = GenStoreShader(m_stage, internalformat, write_value);
3930				const char* const src	= source.c_str();
3931				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3932				glShaderSource(sh, 1, &src, NULL);
3933				glCompileShader(sh);
3934				program_store = glCreateProgram();
3935				glAttachShader(program_store, sh);
3936				glLinkProgram(program_store);
3937				glDeleteShader(sh);
3938			}
3939			{
3940				std::string		  source = GenLoadShader(m_stage, internalformat, expected_value);
3941				const char* const src	= source.c_str();
3942				GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
3943				glShaderSource(sh, 1, &src, NULL);
3944				glCompileShader(sh);
3945				program_load = glCreateProgram();
3946				glAttachShader(program_load, sh);
3947				glLinkProgram(program_load);
3948				glDeleteShader(sh);
3949			}
3950		}
3951		GLuint textures[kTargets], texture_result;
3952		glGenTextures(kTargets, textures);
3953		glGenTextures(1, &texture_result);
3954
3955		glBindTexture(GL_TEXTURE_2D, texture_result);
3956		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3957		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3958		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
3959
3960		for (int i = 0; i < kTargets; ++i)
3961		{
3962			glBindTexture(targets[i], textures[i]);
3963			glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3964			glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3965
3966			if (targets[i] == GL_TEXTURE_1D)
3967			{
3968				glTexStorage1D(targets[i], 1, internalformat, 1);
3969			}
3970			else if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
3971			{
3972				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3973			}
3974			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
3975			{
3976				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
3977			}
3978			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
3979			{
3980				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
3981			}
3982			else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
3983			{
3984				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 12);
3985			}
3986			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
3987			{
3988				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
3989			}
3990		}
3991		glBindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3992		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3993		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3994		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_WRITE_ONLY, internalformat);
3995		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3996		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3997		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3998		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_WRITE_ONLY, internalformat);
3999
4000		glUseProgram(program_store);
4001		glUniform1i(glGetUniformLocation(program_store, "g_image_1d"), 0);
4002		glUniform1i(glGetUniformLocation(program_store, "g_image_2d"), 1);
4003		glUniform1i(glGetUniformLocation(program_store, "g_image_3d"), 2);
4004		glUniform1i(glGetUniformLocation(program_store, "g_image_2drect"), 3);
4005		glUniform1i(glGetUniformLocation(program_store, "g_image_cube"), 4);
4006		glUniform1i(glGetUniformLocation(program_store, "g_image_1darray"), 5);
4007		glUniform1i(glGetUniformLocation(program_store, "g_image_2darray"), 6);
4008		glUniform1i(glGetUniformLocation(program_store, "g_image_cube_array"), 7);
4009
4010		glBindVertexArray(m_vao);
4011		if (m_stage == 1 || m_stage == 2)
4012		{ // TCS or TES
4013			glPatchParameteri(GL_PATCH_VERTICES, 1);
4014			glDrawArrays(GL_PATCHES, 0, 1);
4015			glPatchParameteri(GL_PATCH_VERTICES, 3);
4016		}
4017		else if (m_stage == 4)
4018		{ // CS
4019			glDispatchCompute(1, 1, 1);
4020		}
4021		else
4022		{
4023			glDrawArrays(GL_POINTS, 0, 1);
4024		}
4025
4026		bool status = true;
4027		for (int i = 0; i < kTargets; ++i)
4028		{
4029			glBindTexture(targets[i], textures[i]);
4030			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4031
4032			if (targets[i] == GL_TEXTURE_CUBE_MAP)
4033			{
4034				for (int face = 0; face < 6; ++face)
4035				{
4036					T data;
4037					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, Format<T>(), Type<T>(), &data[0]);
4038					if (!Equal(data, expected_value, internalformat))
4039					{
4040						status = false;
4041						m_context.getTestContext().getLog()
4042							<< tcu::TestLog::Message << "Value is: " << ToString(data)
4043							<< ". Value should be: " << ToString(expected_value)
4044							<< ". Format is: " << FormatEnumToString(internalformat)
4045							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4046							<< tcu::TestLog::EndMessage;
4047					}
4048				}
4049			}
4050			else
4051			{
4052				T data[12];
4053
4054				for (deUint32 ndx = 0; ndx < DE_LENGTH_OF_ARRAY(data); ndx++)
4055					data[ndx] = T(0);
4056
4057				glGetTexImage(targets[i], 0, Format<T>(), Type<T>(), &data[0]);
4058
4059				int count = 1;
4060				if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4061					count = 2;
4062				else if (targets[i] == GL_TEXTURE_CUBE_MAP_ARRAY)
4063					count = 12;
4064				else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4065					count = 2;
4066
4067				for (int j = 0; j < count; ++j)
4068				{
4069					if (!Equal(data[j], expected_value, internalformat))
4070					{
4071						status = false;
4072						m_context.getTestContext().getLog()
4073							<< tcu::TestLog::Message << "Value is: " << ToString(data[j])
4074							<< ". Value should be: " << ToString(expected_value)
4075							<< ". Format is: " << FormatEnumToString(internalformat)
4076							<< ". Target is: " << EnumToString(targets[i]) << ". Stage is: " << StageName(m_stage)
4077							<< tcu::TestLog::EndMessage;
4078					}
4079				}
4080			}
4081		}
4082		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4083		glBindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4084		glBindImageTexture(2, textures[2], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4085		glBindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_ONLY, internalformat);
4086		glBindImageTexture(4, textures[4], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4087		glBindImageTexture(5, textures[5], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4088		glBindImageTexture(6, textures[6], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4089		glBindImageTexture(7, textures[7], 0, GL_TRUE, 0, GL_READ_ONLY, internalformat);
4090
4091		glUseProgram(program_load);
4092		glUniform1i(glGetUniformLocation(program_load, "g_image_result"), 0);
4093		glUniform1i(glGetUniformLocation(program_load, "g_image_2d"), 1);
4094		glUniform1i(glGetUniformLocation(program_load, "g_image_3d"), 2);
4095		glUniform1i(glGetUniformLocation(program_load, "g_image_2drect"), 3);
4096		glUniform1i(glGetUniformLocation(program_load, "g_image_cube"), 4);
4097		glUniform1i(glGetUniformLocation(program_load, "g_image_1darray"), 5);
4098		glUniform1i(glGetUniformLocation(program_load, "g_image_2darray"), 6);
4099		glUniform1i(glGetUniformLocation(program_load, "g_image_cube_array"), 7);
4100
4101		if (m_stage == 1 || m_stage == 2)
4102		{ // TCS or TES
4103			glPatchParameteri(GL_PATCH_VERTICES, 1);
4104			glDrawArrays(GL_PATCHES, 0, 1);
4105			glPatchParameteri(GL_PATCH_VERTICES, 3);
4106		}
4107		else if (m_stage == 4)
4108		{ // CS
4109			glDispatchCompute(1, 1, 1);
4110		}
4111		else
4112		{
4113			glDrawArrays(GL_POINTS, 0, 1);
4114		}
4115		{
4116			vec4 color;
4117			glBindTexture(GL_TEXTURE_2D, texture_result);
4118			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4119			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4120			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4121			{
4122				status = false;
4123				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4124													<< ". Format is: " << FormatEnumToString(internalformat)
4125													<< ". Stage is: " << StageName(m_stage) << tcu::TestLog::EndMessage;
4126			}
4127		}
4128		glUseProgram(0);
4129		glDeleteProgram(program_store);
4130		glDeleteProgram(program_load);
4131		glDeleteTextures(kTargets, textures);
4132		glDeleteTextures(1, &texture_result);
4133		return status;
4134	}
4135
4136	template <typename T>
4137	std::string GenStoreShader(int stage, GLenum internalformat, const T& write_value)
4138	{
4139		std::ostringstream os;
4140		os << "#version 420 core";
4141		if (stage == 4)
4142		{ // CS
4143			os << NL "#extension GL_ARB_compute_shader : require";
4144		}
4145		os << NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4146		   << "image1D g_image_1d;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4147		   << TypePrefix<T>() << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat)
4148		   << ") writeonly uniform " << TypePrefix<T>() << "image3D g_image_3d;" NL "layout("
4149		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4150		   << "image2DRect g_image_2drect;" NL "layout(" << FormatEnumToString(internalformat) << ") writeonly uniform "
4151		   << TypePrefix<T>() << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat)
4152		   << ") writeonly uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4153		   << FormatEnumToString(internalformat) << ") writeonly uniform " << TypePrefix<T>()
4154		   << "image2DArray g_image_2darray;" NL "layout(" << FormatEnumToString(internalformat)
4155		   << ") writeonly uniform " << TypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "uniform "
4156		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << write_value
4157		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4158		if (stage == 0)
4159		{ // VS
4160			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4161		}
4162		else if (stage == 1)
4163		{ // TCS
4164			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4165					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4166					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4167					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4168		}
4169		else if (stage == 2)
4170		{ // TES
4171			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4172					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4173		}
4174		else if (stage == 3)
4175		{ // GS
4176			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4177					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4178		}
4179		else if (stage == 4)
4180		{ // CS
4181			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4182					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4183		}
4184		os << NL "  imageStore(g_image_1d, coord.x, g_value);" NL "  imageStore(g_image_2d, coord, g_value);" NL
4185				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[0]), g_value);" NL
4186				 "  imageStore(g_image_3d, ivec3(coord.xy, g_index[1]), g_value);" NL
4187				 "  imageStore(g_image_2drect, coord, g_value);" NL "  for (int i = 0; i < 6; ++i) {" NL
4188				 "    imageStore(g_image_cube, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4189				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[0]), g_value);" NL
4190				 "  imageStore(g_image_1darray, ivec2(coord.x, g_index[1]), g_value);" NL
4191				 "  imageStore(g_image_2darray, ivec3(coord, g_index[0]), g_value);" NL
4192				 "  imageStore(g_image_2darray, ivec3(coord, g_index[1]), g_value);" NL
4193				 "  for (int i = 0; i < 6; ++i) {" NL
4194				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i]), g_value);" NL "  }" NL
4195				 "  for (int i = 0; i < 6; ++i) {" NL
4196				 "    imageStore(g_image_cube_array, ivec3(coord, g_index[i] + 6), g_value);" NL "  }" NL "}";
4197		return os.str();
4198	}
4199
4200	template <typename T>
4201	std::string GenLoadShader(int stage, GLenum internalformat, const T& expected_value)
4202	{
4203		std::ostringstream os;
4204		os << "#version 420 core";
4205		if (stage == 4)
4206		{ // CS
4207			os << NL "#extension GL_ARB_compute_shader : require";
4208		}
4209		os << NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4210		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4211		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4212		   << ") readonly uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4213		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4214		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") readonly uniform "
4215		   << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout(" << FormatEnumToString(internalformat)
4216		   << ") readonly uniform " << TypePrefix<T>() << "image2DArray g_image_2darray;" NL "layout("
4217		   << FormatEnumToString(internalformat) << ") readonly uniform " << TypePrefix<T>()
4218		   << "imageCubeArray g_image_cube_array;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4219			  "uniform "
4220		   << TypePrefix<T>() << "vec4 g_value = " << TypePrefix<T>() << "vec4" << expected_value
4221		   << ";" NL "uniform int g_index[6] = int[](0, 1, 2, 3, 4, 5);";
4222		if (stage == 0)
4223		{ // VS
4224			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_index[0]);";
4225		}
4226		else if (stage == 1)
4227		{ // TCS
4228			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4229					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4230					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4231					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4232		}
4233		else if (stage == 2)
4234		{ // TES
4235			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4236					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_index[0]);";
4237		}
4238		else if (stage == 3)
4239		{ // GS
4240			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4241					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_index[0]);";
4242		}
4243		else if (stage == 4)
4244		{ // CS
4245			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4246					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_index[0]);";
4247		}
4248		os << NL "  vec4 r = vec4(0, 1, 0, 1);" NL "  " << TypePrefix<T>()
4249		   << "vec4 v;" NL "  v = imageLoad(g_image_2d, coord);" NL
4250			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4251			  "  v = imageLoad(g_image_3d, ivec3(coord, g_index[0]));" NL
4252			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_2drect, coord);" NL
4253			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4254			  "  v = imageLoad(g_image_cube, ivec3(coord, g_index[0]));" NL
4255			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  v = imageLoad(g_image_1darray, coord);" NL
4256			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4257			  "  v = imageLoad(g_image_2darray, ivec3(coord, g_index[0]));" NL
4258			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL
4259			  "  v = imageLoad(g_image_cube_array, ivec3(coord, g_index[0]));" NL
4260			  "  if (v != g_value) r = vec4(1.0, 0.0, 0.0, 1.0);" NL "  imageStore(g_image_result, coord, r);" NL "}";
4261		return os.str();
4262	}
4263
4264protected:
4265	long RunStage(int stage)
4266	{
4267		if (!SupportedInStage(stage, 8))
4268			return NOT_SUPPORTED;
4269
4270		glEnable(GL_RASTERIZER_DISCARD);
4271		m_stage = stage;
4272
4273		if (!Write(GL_RGBA32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4274			return ERROR;
4275		if (!Write(GL_RG32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4276			return ERROR;
4277		if (!Write(GL_R32F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4278			return ERROR;
4279
4280		if (!Write(GL_RGBA16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 4.0f)))
4281			return ERROR;
4282		if (!Write(GL_RG16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 0.0f, 1.0f)))
4283			return ERROR;
4284		if (!Write(GL_R16F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4285			return ERROR;
4286
4287		if (!Write(GL_RGBA32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4288			return ERROR;
4289		if (!Write(GL_RG32I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4290			return ERROR;
4291		if (!Write(GL_R32I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4292			return ERROR;
4293
4294		if (!Write(GL_R11F_G11F_B10F, vec4(1.0f, 2.0f, 3.0f, 4.0f), vec4(1.0f, 2.0f, 3.0f, 1.0f)))
4295			return ERROR;
4296
4297		if (!Write(GL_RGBA16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4298			return ERROR;
4299		if (!Write(GL_RG16I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4300			return ERROR;
4301		if (!Write(GL_R16I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4302			return ERROR;
4303
4304		if (!Write(GL_RGBA8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 3, -4)))
4305			return ERROR;
4306		if (!Write(GL_RG8I, ivec4(1, -2, 3, -4), ivec4(1, -2, 0, 1)))
4307			return ERROR;
4308		if (!Write(GL_R8I, ivec4(1, -2, 3, -4), ivec4(1, 0, 0, 1)))
4309			return ERROR;
4310
4311		if (!Write(GL_RGBA32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4312			return ERROR;
4313		if (!Write(GL_RGB10_A2UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4314			return ERROR;
4315		if (!Write(GL_RG32UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4316			return ERROR;
4317		if (!Write(GL_R32UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4318			return ERROR;
4319
4320		if (!Write(GL_RGBA16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4321			return ERROR;
4322		if (!Write(GL_RG16UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4323			return ERROR;
4324		if (!Write(GL_R16UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4325			return ERROR;
4326
4327		if (!Write(GL_RGBA8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 2, 3)))
4328			return ERROR;
4329		if (!Write(GL_RG8UI, uvec4(0, 1, 2, 3), uvec4(0, 1, 0, 1)))
4330			return ERROR;
4331		if (!Write(GL_R8UI, uvec4(7, 2, 3, 4), uvec4(7, 0, 0, 1)))
4332			return ERROR;
4333
4334		if (!Write(GL_RGBA16, vec4(1.0f), vec4(1.0f)))
4335			return ERROR;
4336		if (!Write(GL_RGB10_A2, vec4(1.0f), vec4(1.0f)))
4337			return ERROR;
4338		if (!Write(GL_RG16, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4339			return ERROR;
4340		if (!Write(GL_R16, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4341			return ERROR;
4342
4343		if (!Write(GL_RGBA8, vec4(1.0f), vec4(1.0f)))
4344			return ERROR;
4345		if (!Write(GL_RG8, vec4(1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f)))
4346			return ERROR;
4347		if (!Write(GL_R8, vec4(1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f)))
4348			return ERROR;
4349
4350		//
4351		{
4352			if (!Write(GL_RGBA16_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4353				return ERROR;
4354			if (!Write(GL_RG16_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4355				return ERROR;
4356			if (!Write(GL_R16_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4357				return ERROR;
4358
4359			if (!Write(GL_RGBA8_SNORM, vec4(1.0f, -1.0f, 1.0f, -1.0f), vec4(1.0f, -1.0f, 1.0f, -1.0f)))
4360				return ERROR;
4361			if (!Write(GL_RG8_SNORM, vec4(-1.0f), vec4(-1.0f, -1.0f, 0.0f, 1.0f)))
4362				return ERROR;
4363			if (!Write(GL_R8_SNORM, vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(-1.0f, 0.0f, 0.0f, 1.0f)))
4364				return ERROR;
4365		}
4366		return NO_ERROR;
4367	}
4368};
4369//-----------------------------------------------------------------------------
4370// AtomicMachine
4371//-----------------------------------------------------------------------------
4372class AtomicMachine : public ShaderImageLoadStoreBase
4373{
4374	GLuint m_vao;
4375
4376	virtual long Setup()
4377	{
4378		glEnable(GL_RASTERIZER_DISCARD);
4379		glGenVertexArrays(1, &m_vao);
4380		return NO_ERROR;
4381	}
4382
4383	virtual long Cleanup()
4384	{
4385		glDisable(GL_RASTERIZER_DISCARD);
4386		glDeleteVertexArrays(1, &m_vao);
4387		return NO_ERROR;
4388	}
4389
4390	template <typename T>
4391	bool Atomic(int stage, GLenum internalformat)
4392	{
4393		GLuint program = 0;
4394		if (stage == 0)
4395		{ // VS
4396			program = BuildProgram(GenShader<T>(stage, internalformat).c_str(), NULL, NULL, NULL, NULL);
4397		}
4398		else if (stage == 1)
4399		{ // TCS
4400			const char* const glsl_vs  = "#version 420 core" NL "void main() {}";
4401			const char* const glsl_tes = "#version 420 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
4402			program = BuildProgram(glsl_vs, GenShader<T>(stage, internalformat).c_str(), glsl_tes, NULL, NULL);
4403		}
4404		else if (stage == 2)
4405		{ // TES
4406			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4407			program = BuildProgram(glsl_vs, NULL, GenShader<T>(stage, internalformat).c_str(), NULL, NULL);
4408		}
4409		else if (stage == 3)
4410		{ // GS
4411			const char* const glsl_vs = "#version 420 core" NL "void main() {}";
4412			program = BuildProgram(glsl_vs, NULL, NULL, GenShader<T>(stage, internalformat).c_str(), NULL);
4413		}
4414		else if (stage == 4)
4415		{ // CS
4416			std::string		  source = GenShader<T>(stage, internalformat);
4417			const char* const src	= source.c_str();
4418			GLuint			  sh	 = glCreateShader(GL_COMPUTE_SHADER);
4419			glShaderSource(sh, 1, &src, NULL);
4420			glCompileShader(sh);
4421			program = glCreateProgram();
4422			glAttachShader(program, sh);
4423			glLinkProgram(program);
4424			glDeleteShader(sh);
4425		}
4426		GLuint texture_result;
4427		glGenTextures(1, &texture_result);
4428		glBindTexture(GL_TEXTURE_2D, texture_result);
4429		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4430		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4431		glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1);
4432
4433		const GLenum targets[] = { GL_TEXTURE_2D,	 GL_TEXTURE_3D,	   GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP,
4434								   GL_TEXTURE_BUFFER, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY };
4435		const int kTargets = sizeof(targets) / sizeof(targets[0]);
4436
4437		GLuint textures[kTargets];
4438		GLuint buffer;
4439		glGenTextures(kTargets, textures);
4440		glGenBuffers(1, &buffer);
4441
4442		for (int i = 0; i < kTargets; ++i)
4443		{
4444			glBindTexture(targets[i], textures[i]);
4445			if (targets[i] != GL_TEXTURE_BUFFER)
4446			{
4447				glTexParameteri(targets[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4448				glTexParameteri(targets[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4449			}
4450			if (targets[i] == GL_TEXTURE_2D || targets[i] == GL_TEXTURE_RECTANGLE)
4451			{
4452				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4453			}
4454			else if (targets[i] == GL_TEXTURE_3D || targets[i] == GL_TEXTURE_2D_ARRAY)
4455			{
4456				glTexStorage3D(targets[i], 1, internalformat, 1, 1, 2);
4457			}
4458			else if (targets[i] == GL_TEXTURE_CUBE_MAP)
4459			{
4460				glTexStorage2D(targets[i], 1, internalformat, 1, 1);
4461			}
4462			else if (targets[i] == GL_TEXTURE_BUFFER)
4463			{
4464				glBindBuffer(GL_TEXTURE_BUFFER, buffer);
4465				glBufferData(GL_TEXTURE_BUFFER, 4, NULL, GL_DYNAMIC_DRAW);
4466				glBindBuffer(GL_TEXTURE_BUFFER, 0);
4467				glTexBuffer(targets[i], internalformat, buffer);
4468			}
4469			else if (targets[i] == GL_TEXTURE_1D_ARRAY)
4470			{
4471				glTexStorage2D(targets[i], 1, internalformat, 1, 2);
4472			}
4473		}
4474		glBindImageTexture(0, texture_result, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
4475		glBindImageTexture(1, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4476		glBindImageTexture(2, textures[1], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4477		glBindImageTexture(3, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4478		glBindImageTexture(4, textures[3], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4479		glBindImageTexture(5, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, internalformat);
4480		glBindImageTexture(6, textures[5], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4481		glBindImageTexture(7, textures[6], 0, GL_TRUE, 0, GL_READ_WRITE, internalformat);
4482
4483		glUseProgram(program);
4484		glUniform1i(glGetUniformLocation(program, "g_image_result"), 0);
4485		glUniform1i(glGetUniformLocation(program, "g_image_2d"), 1);
4486		glUniform1i(glGetUniformLocation(program, "g_image_3d"), 2);
4487		glUniform1i(glGetUniformLocation(program, "g_image_2drect"), 3);
4488		glUniform1i(glGetUniformLocation(program, "g_image_cube"), 4);
4489		glUniform1i(glGetUniformLocation(program, "g_image_buffer"), 5);
4490		glUniform1i(glGetUniformLocation(program, "g_image_1darray"), 6);
4491		glUniform1i(glGetUniformLocation(program, "g_image_2darray"), 7);
4492
4493		glBindVertexArray(m_vao);
4494		if (stage == 1 || stage == 2)
4495		{ // TCS or TES
4496			glPatchParameteri(GL_PATCH_VERTICES, 1);
4497			glDrawArrays(GL_PATCHES, 0, 1);
4498			glPatchParameteri(GL_PATCH_VERTICES, 3);
4499		}
4500		else if (stage == 4)
4501		{ // CS
4502			glDispatchCompute(1, 1, 1);
4503		}
4504		else
4505		{
4506			glDrawArrays(GL_POINTS, 0, 1);
4507		}
4508
4509		bool status = true;
4510		{
4511			vec4 color;
4512			glBindTexture(GL_TEXTURE_2D, texture_result);
4513			glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4514			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &color[0]);
4515			if (!tcu::allEqual(color, vec4(0, 1, 0, 1)))
4516			{
4517				status = false;
4518				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Color is: " << ToString(color)
4519													<< ". Format is: " << FormatEnumToString(internalformat)
4520													<< ". Stage is: " << StageName(stage) << tcu::TestLog::EndMessage;
4521			}
4522		}
4523		glUseProgram(0);
4524		glDeleteProgram(program);
4525		glDeleteTextures(7, textures);
4526		glDeleteTextures(1, &texture_result);
4527		glDeleteBuffers(1, &buffer);
4528		return status;
4529	}
4530
4531	template <typename T>
4532	std::string GenShader(int stage, GLenum internalformat)
4533	{
4534		std::ostringstream os;
4535		os << "#version 420 core";
4536		if (stage == 4)
4537		{ // CS
4538			os << NL "#extension GL_ARB_compute_shader : require";
4539		}
4540		os << NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4541		   << "image2D g_image_2d;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4542		   << TypePrefix<T>() << "image3D g_image_3d;" NL "layout(" << FormatEnumToString(internalformat)
4543		   << ") coherent uniform " << TypePrefix<T>() << "image2DRect g_image_2drect;" NL "layout("
4544		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4545		   << "imageCube g_image_cube;" NL "layout(" << FormatEnumToString(internalformat) << ") coherent uniform "
4546		   << TypePrefix<T>() << "imageBuffer g_image_buffer;" NL "layout(" << FormatEnumToString(internalformat)
4547		   << ") coherent uniform " << TypePrefix<T>() << "image1DArray g_image_1darray;" NL "layout("
4548		   << FormatEnumToString(internalformat) << ") coherent uniform " << TypePrefix<T>()
4549		   << "image2DArray g_image_2darray;" NL "layout(rgba32f) writeonly uniform image2D g_image_result;" NL
4550			  "uniform int g_value[6] = int[](0, 1, 2, 3, 4, 5);";
4551		if (stage == 0)
4552		{ // VS
4553			os << NL "void main() {" NL "  ivec2 coord = ivec2(gl_VertexID, g_value[0]);";
4554		}
4555		else if (stage == 1)
4556		{ // TCS
4557			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
4558					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
4559					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL
4560					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4561		}
4562		else if (stage == 2)
4563		{ // TES
4564			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL
4565					 "  ivec2 coord = ivec2(gl_PrimitiveID, g_value[0]);";
4566		}
4567		else if (stage == 3)
4568		{ // GS
4569			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
4570					 "  ivec2 coord = ivec2(gl_PrimitiveIDIn, g_value[0]);";
4571		}
4572		else if (stage == 4)
4573		{ // CS
4574			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL
4575					 "  ivec2 coord = ivec2(gl_GlobalInvocationID.x, g_value[0]);";
4576		}
4577		os << NL
4578			"  vec4 o_color = vec4(0, 1, 0, 1);" NL "  imageAtomicExchange(g_image_2d, coord, 0);" NL
4579			"  if (imageAtomicAdd(g_image_2d, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4580			"  if (imageAtomicMin(g_image_2d, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4581			"  if (imageAtomicMax(g_image_2d, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4582			"  if (imageAtomicAnd(g_image_2d, coord, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4583			"  if (imageAtomicOr(g_image_2d, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4584			"  if (imageAtomicXor(g_image_2d, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4585			"  if (imageAtomicExchange(g_image_2d, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4586			"  if (imageAtomicCompSwap(g_image_2d, coord, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4587			"  if (imageAtomicExchange(g_image_2d, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4588
4589			NL "  imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0);" NL
4590			"  if (imageAtomicAdd(g_image_3d, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4591			"  if (imageAtomicMin(g_image_3d, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4592			"  if (imageAtomicMax(g_image_3d, ivec3(coord, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4593			"  if (imageAtomicAnd(g_image_3d, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4594			"  if (imageAtomicOr(g_image_3d, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4595			"  if (imageAtomicXor(g_image_3d, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4596			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4597			"  if (imageAtomicCompSwap(g_image_3d, ivec3(coord, 0), 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4598			"  if (imageAtomicExchange(g_image_3d, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4599
4600			NL "  imageAtomicExchange(g_image_2drect, coord, 0);" NL
4601			"  if (imageAtomicAdd(g_image_2drect, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4602			"  if (imageAtomicMin(g_image_2drect, coord, 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4603			"  if (imageAtomicMax(g_image_2drect, coord, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4604			"  if (imageAtomicAnd(g_image_2drect, coord, 0) != g_value[4]) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4605			"  if (imageAtomicOr(g_image_2drect, coord, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4606			"  if (imageAtomicXor(g_image_2drect, coord, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4607			"  if (imageAtomicExchange(g_image_2drect, coord, 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4608			"  if (imageAtomicCompSwap(g_image_2drect, coord, g_value[1], 6) != 1) o_color = vec4(1.0, 0.0, 0.0, "
4609			"1.0);" NL "  if (imageAtomicExchange(g_image_2drect, coord, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4610
4611			NL "  imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0);" NL "  if (imageAtomicAdd(g_image_cube, "
4612			"ivec3(coord, 0), g_value[2]) != 0) "
4613			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4614			"  if (imageAtomicMin(g_image_cube, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4615			"  if (imageAtomicMax(g_image_cube, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4616			"  if (imageAtomicAnd(g_image_cube, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4617			"  if (imageAtomicOr(g_image_cube, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4618			"  if (imageAtomicXor(g_image_cube, ivec3(coord, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4619			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4620			"  if (imageAtomicCompSwap(g_image_cube, ivec3(coord, g_value[0]), 1, 6) != 1) o_color = vec4(1.0, 0.0, "
4621			"0.0, 1.0);" NL
4622			"  if (imageAtomicExchange(g_image_cube, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4623
4624			NL "  imageAtomicExchange(g_image_buffer, coord.x, g_value[0]);" NL
4625			"  if (imageAtomicAdd(g_image_buffer, coord.x, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4626			"  if (imageAtomicMin(g_image_buffer, coord.x, g_value[3]) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4627			"  if (imageAtomicMax(g_image_buffer, coord.x, 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4628			"  if (imageAtomicAnd(g_image_buffer, coord.x, 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4629			"  if (imageAtomicOr(g_image_buffer, coord.x, 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4630			"  if (imageAtomicXor(g_image_buffer, coord.x, 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4631			"  if (imageAtomicExchange(g_image_buffer, coord.x, g_value[1]) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4632			"1.0);" NL
4633			"  if (imageAtomicCompSwap(g_image_buffer, coord.x, 1, 6) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4634			"  if (imageAtomicExchange(g_image_buffer, coord.x, 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4635
4636			NL "  imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0);" NL
4637			"  if (imageAtomicAdd(g_image_1darray, ivec2(coord.x, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4638			"  if (imageAtomicMin(g_image_1darray, ivec2(coord.x, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4639			"  if (imageAtomicMax(g_image_1darray, ivec2(coord.x, g_value[0]), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, "
4640			"1.0);" NL
4641			"  if (imageAtomicAnd(g_image_1darray, ivec2(coord.x, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4642			"  if (imageAtomicOr(g_image_1darray, ivec2(coord.x, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4643			"  if (imageAtomicXor(g_image_1darray, ivec2(coord.x, 0), 4) != 7) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4644			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 1) != 3) o_color = vec4(1.0, 0.0, 0.0, "
4645			"1.0);" NL "  if (imageAtomicCompSwap(g_image_1darray, ivec2(coord.x, 0), 1, 6) != 1) o_color = vec4(1.0, "
4646			"0.0, 0.0, 1.0);" NL
4647			"  if (imageAtomicExchange(g_image_1darray, ivec2(coord.x, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4648
4649			NL "  imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0);" NL
4650			"  if (imageAtomicAdd(g_image_2darray, ivec3(coord, 0), 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4651			"  if (imageAtomicMin(g_image_2darray, ivec3(coord, 0), 3) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4652			"  if (imageAtomicMax(g_image_2darray, ivec3(coord, 0), 4) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4653			"  if (imageAtomicAnd(g_image_2darray, ivec3(coord, 0), 0) != 4) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4654			"  if (imageAtomicOr(g_image_2darray, ivec3(coord, 0), 7) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4655			"  if (imageAtomicXor(g_image_2darray, ivec3(coord, 0), g_value[4]) != 7) o_color = vec4(1.0, 0.0, 0.0, "
4656			"1.0);" NL "  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 1) != 3) o_color = vec4(1.0, 0.0, "
4657			"0.0, 1.0);" NL "  if (imageAtomicCompSwap(g_image_2darray, ivec3(coord, 0), 1, 6) != 1) "
4658			"o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
4659			"  if (imageAtomicExchange(g_image_2darray, ivec3(coord, 0), 0) != 6) o_color = vec4(1.0, 0.0, 0.0, 1.0);"
4660
4661			NL "  imageStore(g_image_result, coord, o_color);" NL "}";
4662		return os.str();
4663	}
4664
4665protected:
4666	long RunStage(int stage)
4667	{
4668		if (!SupportedInStage(stage, 8))
4669			return NOT_SUPPORTED;
4670		if (!Atomic<GLint>(stage, GL_R32I))
4671			return ERROR;
4672		if (!Atomic<GLuint>(stage, GL_R32UI))
4673			return ERROR;
4674		return NO_ERROR;
4675	}
4676};
4677//-----------------------------------------------------------------------------
4678// 1.3.4 BasicAllTargetsLoadStoreVS
4679//-----------------------------------------------------------------------------
4680class BasicAllTargetsLoadStoreVS : public LoadStoreMachine
4681{
4682	virtual long Run()
4683	{
4684		return RunStage(0);
4685	}
4686};
4687//-----------------------------------------------------------------------------
4688// 1.3.5 BasicAllTargetsLoadStoreTCS
4689//-----------------------------------------------------------------------------
4690class BasicAllTargetsLoadStoreTCS : public LoadStoreMachine
4691{
4692	virtual long Run()
4693	{
4694		return RunStage(1);
4695	}
4696};
4697//-----------------------------------------------------------------------------
4698// 1.3.6 BasicAllTargetsLoadStoreTES
4699//-----------------------------------------------------------------------------
4700class BasicAllTargetsLoadStoreTES : public LoadStoreMachine
4701{
4702	virtual long Run()
4703	{
4704		return RunStage(2);
4705	}
4706};
4707//-----------------------------------------------------------------------------
4708// 1.3.7 BasicAllTargetsLoadStoreGS
4709//-----------------------------------------------------------------------------
4710class BasicAllTargetsLoadStoreGS : public LoadStoreMachine
4711{
4712	virtual long Run()
4713	{
4714		return RunStage(3);
4715	}
4716};
4717//-----------------------------------------------------------------------------
4718// 1.3.8 BasicAllTargetsLoadStoreCS
4719//-----------------------------------------------------------------------------
4720class BasicAllTargetsLoadStoreCS : public LoadStoreMachine
4721{
4722	virtual long Run()
4723	{
4724		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4725		{
4726			m_context.getTestContext().getLog()
4727				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4728				<< tcu::TestLog::EndMessage;
4729			return NO_ERROR;
4730		}
4731
4732		return RunStage(4);
4733	}
4734};
4735//-----------------------------------------------------------------------------
4736// 1.3.9 BasicAllTargetsAtomicVS
4737//-----------------------------------------------------------------------------
4738class BasicAllTargetsAtomicVS : public AtomicMachine
4739{
4740	virtual long Run()
4741	{
4742		return RunStage(0);
4743	}
4744};
4745//-----------------------------------------------------------------------------
4746// 1.3.10 BasicAllTargetsAtomicTCS
4747//-----------------------------------------------------------------------------
4748class BasicAllTargetsAtomicTCS : public AtomicMachine
4749{
4750	virtual long Run()
4751	{
4752		return RunStage(1);
4753	}
4754};
4755//-----------------------------------------------------------------------------
4756// 1.3.11 BasicAllTargetsAtomicTES
4757//-----------------------------------------------------------------------------
4758class BasicAllTargetsAtomicTES : public AtomicMachine
4759{
4760	virtual long Run()
4761	{
4762		return RunStage(2);
4763	}
4764};
4765//-----------------------------------------------------------------------------
4766// 1.3.12 BasicAllTargetsAtomicGS
4767//-----------------------------------------------------------------------------
4768class BasicAllTargetsAtomicGS : public AtomicMachine
4769{
4770	virtual long Run()
4771	{
4772		return RunStage(3);
4773	}
4774};
4775//-----------------------------------------------------------------------------
4776// 1.3.13 BasicAllTargetsAtomicCS
4777//-----------------------------------------------------------------------------
4778class BasicAllTargetsAtomicCS : public AtomicMachine
4779{
4780	virtual long Run()
4781	{
4782		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
4783		{
4784			m_context.getTestContext().getLog()
4785				<< tcu::TestLog::Message << "GL_ARB_compute_shader not supported, skipping test"
4786				<< tcu::TestLog::EndMessage;
4787			return NO_ERROR;
4788		}
4789
4790		return RunStage(4);
4791	}
4792};
4793//-----------------------------------------------------------------------------
4794// 1.4.1 BasicGLSLMisc
4795//-----------------------------------------------------------------------------
4796class BasicGLSLMisc : public ShaderImageLoadStoreBase
4797{
4798	GLuint m_texture;
4799	GLuint m_program;
4800	GLuint m_vao, m_vbo;
4801
4802	virtual long Setup()
4803	{
4804		m_texture = 0;
4805		m_program = 0;
4806		m_vao = m_vbo = 0;
4807		return NO_ERROR;
4808	}
4809
4810	virtual long Run()
4811	{
4812		const int		  kSize = 32;
4813		std::vector<vec4> data(kSize * kSize * 4, vec4(0.0f));
4814
4815		glGenTextures(1, &m_texture);
4816		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
4817		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4818		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, kSize, kSize, 4, 0, GL_RGBA, GL_FLOAT, &data[0]);
4819		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
4820
4821		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4822							 "  gl_Position = i_position;" NL "}";
4823		const char* src_fs =
4824			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4825			"layout(rgba32f) coherent volatile restrict uniform image2D g_image_layer0;" NL
4826			"layout(rgba32f) volatile uniform image2D g_image_layer1;" NL
4827			"void main() {" NL "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL
4828			"  imageStore(g_image_layer0, coord, vec4(1.0));" NL "  memoryBarrier();" NL
4829			"  imageStore(g_image_layer0, coord, vec4(2.0));" NL "  memoryBarrier();" NL
4830			"  imageStore(g_image_layer0, coord, vec4(0.0, 1.0, 0.0, 1.0));" NL "  memoryBarrier();" NL
4831			"  o_color = imageLoad(g_image_layer0, coord) + imageLoad(g_image_layer1, coord);" NL "}";
4832		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs);
4833
4834		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4835
4836		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4837		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_ONLY, GL_RGBA32F);
4838
4839		glClear(GL_COLOR_BUFFER_BIT);
4840		glViewport(0, 0, kSize, kSize);
4841
4842		glUseProgram(m_program);
4843		glUniform1i(glGetUniformLocation(m_program, "g_image_layer0"), 0);
4844		glUniform1i(glGetUniformLocation(m_program, "g_image_layer1"), 1);
4845
4846		glBindVertexArray(m_vao);
4847		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4848
4849		if (!ValidateReadBuffer(0, 0, kSize, kSize, vec4(0, 1, 0, 1)))
4850		{
4851			return ERROR;
4852		}
4853		return NO_ERROR;
4854	}
4855
4856	virtual long Cleanup()
4857	{
4858		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4859		glDeleteTextures(1, &m_texture);
4860		glDeleteVertexArrays(1, &m_vao);
4861		glDeleteBuffers(1, &m_vbo);
4862		glUseProgram(0);
4863		glDeleteProgram(m_program);
4864		return NO_ERROR;
4865	}
4866};
4867//-----------------------------------------------------------------------------
4868// 1.4.2 BasicGLSLEarlyFragTests
4869//-----------------------------------------------------------------------------
4870class BasicGLSLEarlyFragTests : public ShaderImageLoadStoreBase
4871{
4872	GLuint m_texture[2];
4873	GLuint m_program[2];
4874	GLuint m_vao, m_vbo;
4875
4876	virtual long Setup()
4877	{
4878		m_texture[0] = m_texture[1] = 0;
4879		m_program[0] = m_program[1] = 0;
4880		m_vao = m_vbo = 0;
4881		return NO_ERROR;
4882	}
4883
4884	virtual long Run()
4885	{
4886		int ds = m_context.getRenderContext().getRenderTarget().getDepthBits();
4887
4888		const int		  kSize = 32;
4889		std::vector<vec4> data(kSize * kSize);
4890
4891		glGenTextures(2, m_texture);
4892		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4893		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4894		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4895		glBindTexture(GL_TEXTURE_2D, 0);
4896
4897		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4898		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4899		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, kSize, kSize, 0, GL_RGBA, GL_FLOAT, &data[0]);
4900		glBindTexture(GL_TEXTURE_2D, 0);
4901
4902		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4903							  "  gl_Position = i_position;" NL "}";
4904		const char* glsl_early_frag_tests_fs =
4905			"#version 420 core" NL "layout(early_fragment_tests) in;" NL "layout(location = 0) out vec4 o_color;" NL
4906			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4907			"  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4908			"  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4909		const char* glsl_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
4910							  "layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL
4911							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(1.0));" NL
4912							  "  o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
4913		m_program[0] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_early_frag_tests_fs);
4914		m_program[1] = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
4915
4916		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
4917
4918		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4919		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
4920
4921		glViewport(0, 0, kSize, kSize);
4922		glBindVertexArray(m_vao);
4923
4924		glEnable(GL_DEPTH_TEST);
4925		glClearColor(0.0, 1.0f, 0.0, 1.0f);
4926		glClearDepthf(0.0f);
4927
4928		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4929		glUseProgram(m_program[0]);
4930		glUniform1i(glGetUniformLocation(m_program[0], "g_image"), 0);
4931
4932		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4933
4934		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4935		glUseProgram(m_program[1]);
4936		glUniform1i(glGetUniformLocation(m_program[1], "g_image"), 1);
4937		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4938
4939		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
4940		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4941		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4942		for (int i = 0; i < kSize * kSize; ++i)
4943		{
4944			if (IsEqual(data[i], vec4(1.0f)) && ds != 0)
4945				return ERROR;
4946		}
4947
4948		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
4949		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
4950		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &data[0]);
4951		for (int i = 0; i < kSize * kSize; ++i)
4952		{
4953			if (!IsEqual(data[i], vec4(1.0f)) && ds != 0)
4954				return ERROR;
4955		}
4956
4957		return NO_ERROR;
4958	}
4959
4960	virtual long Cleanup()
4961	{
4962		glDisable(GL_DEPTH_TEST);
4963		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
4964		glClearDepthf(1.0f);
4965		glViewport(0, 0, getWindowWidth(), getWindowHeight());
4966		glDeleteTextures(2, m_texture);
4967		glDeleteVertexArrays(1, &m_vao);
4968		glDeleteBuffers(1, &m_vbo);
4969		glUseProgram(0);
4970		glDeleteProgram(m_program[0]);
4971		glDeleteProgram(m_program[1]);
4972		return NO_ERROR;
4973	}
4974};
4975//-----------------------------------------------------------------------------
4976// 1.4.3 BasicGLSLConst
4977//-----------------------------------------------------------------------------
4978class BasicGLSLConst : public ShaderImageLoadStoreBase
4979{
4980	GLuint m_program;
4981	GLuint m_vao, m_vbo;
4982
4983	virtual long Setup()
4984	{
4985		m_program = 0;
4986		m_vao = m_vbo = 0;
4987		return NO_ERROR;
4988	}
4989
4990	virtual long Run()
4991	{
4992		bool isAtLeast44Context =
4993			glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 4));
4994
4995		const char* src_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
4996							 "  gl_Position = i_position;" NL "}";
4997		std::ostringstream src_fs;
4998		src_fs << "#version " << (isAtLeast44Context ? "440" : "420") << " core";
4999		src_fs << NL "layout(location = 0) out vec4 o_color;" NL "uniform int MaxImageUnits;" NL
5000					 "uniform int MaxCombinedShaderOutputResources;" NL "uniform int MaxImageSamples;" NL
5001					 "uniform int MaxVertexImageUniforms;" NL "uniform int MaxTessControlImageUniforms;" NL
5002					 "uniform int MaxTessEvaluationImageUniforms;" NL "uniform int MaxGeometryImageUniforms;" NL
5003					 "uniform int MaxFragmentImageUniforms;" NL "uniform int MaxCombinedImageUniforms;" NL
5004					 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL
5005					 "  if (gl_MaxImageUnits != MaxImageUnits) o_color = vec4(1.0, 0.0, 0.0, 0.1);";
5006		if (isAtLeast44Context)
5007			src_fs << NL "  if (gl_MaxCombinedShaderOutputResources != MaxCombinedShaderOutputResources) o_color = "
5008						 "vec4(0.2, 0.0, 0.0, 0.2);";
5009		else
5010			src_fs << NL "  if (gl_MaxCombinedImageUnitsAndFragmentOutputs != MaxCombinedShaderOutputResources) "
5011						 "o_color = vec4(0.2, 0.0, 0.0, 0.2);";
5012		src_fs << NL
5013			"  if (gl_MaxImageSamples != MaxImageSamples) o_color = vec4(1.0, 0.0, 0.0, 0.3);" NL
5014			"  if (gl_MaxVertexImageUniforms != MaxVertexImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.4);" NL
5015			"  if (gl_MaxTessControlImageUniforms != MaxTessControlImageUniforms) o_color = vec4(1.0, 0.0, 0.0, "
5016			"0.5);" NL "  if (gl_MaxTessEvaluationImageUniforms != MaxTessEvaluationImageUniforms) o_color = vec4(1.0, "
5017			"0.0, 0.0, 0.6);" NL
5018			"  if (gl_MaxGeometryImageUniforms != MaxGeometryImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.7);" NL
5019			"  if (gl_MaxFragmentImageUniforms != MaxFragmentImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.8);" NL
5020			"  if (gl_MaxCombinedImageUniforms != MaxCombinedImageUniforms) o_color = vec4(1.0, 0.0, 0.0, 0.9);" NL "}";
5021
5022		m_program = BuildProgram(src_vs, NULL, NULL, NULL, src_fs.str().c_str());
5023		glUseProgram(m_program);
5024
5025		GLint i;
5026		glGetIntegerv(GL_MAX_IMAGE_UNITS, &i);
5027		glUniform1i(glGetUniformLocation(m_program, "MaxImageUnits"), i);
5028
5029		glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &i);
5030		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedShaderOutputResources"), i);
5031
5032		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
5033		glUniform1i(glGetUniformLocation(m_program, "MaxImageSamples"), i);
5034
5035		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &i);
5036		glUniform1i(glGetUniformLocation(m_program, "MaxVertexImageUniforms"), i);
5037
5038		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &i);
5039		glUniform1i(glGetUniformLocation(m_program, "MaxTessControlImageUniforms"), i);
5040
5041		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &i);
5042		glUniform1i(glGetUniformLocation(m_program, "MaxTessEvaluationImageUniforms"), i);
5043
5044		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &i);
5045		glUniform1i(glGetUniformLocation(m_program, "MaxGeometryImageUniforms"), i);
5046
5047		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &i);
5048		glUniform1i(glGetUniformLocation(m_program, "MaxFragmentImageUniforms"), i);
5049
5050		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &i);
5051		glUniform1i(glGetUniformLocation(m_program, "MaxCombinedImageUniforms"), i);
5052
5053		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5054
5055		glClear(GL_COLOR_BUFFER_BIT);
5056		glBindVertexArray(m_vao);
5057		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5058
5059		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5060		{
5061			return ERROR;
5062		}
5063		return NO_ERROR;
5064	}
5065
5066	virtual long Cleanup()
5067	{
5068		glDeleteVertexArrays(1, &m_vao);
5069		glDeleteBuffers(1, &m_vbo);
5070		glUseProgram(0);
5071		glDeleteProgram(m_program);
5072		return NO_ERROR;
5073	}
5074};
5075//-----------------------------------------------------------------------------
5076// 2.1.1 AdvancedSyncImageAccess
5077//-----------------------------------------------------------------------------
5078class AdvancedSyncImageAccess : public ShaderImageLoadStoreBase
5079{
5080	GLuint m_buffer;
5081	GLuint m_buffer_tex;
5082	GLuint m_store_program;
5083	GLuint m_draw_program;
5084	GLuint m_attribless_vao;
5085
5086	virtual long Setup()
5087	{
5088		m_buffer		 = 0;
5089		m_buffer_tex	 = 0;
5090		m_store_program  = 0;
5091		m_draw_program   = 0;
5092		m_attribless_vao = 0;
5093		return NO_ERROR;
5094	}
5095
5096	virtual long Run()
5097	{
5098		if (!SupportedInVS(1))
5099			return NOT_SUPPORTED;
5100		const char* const glsl_store_vs =
5101			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5102			"  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5103			"  imageStore(g_output_data, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL "}";
5104		const char* const glsl_draw_vs =
5105			"#version 420 core" NL "out vec4 vs_color;" NL "layout(rg32f) readonly uniform imageBuffer g_image;" NL
5106			"uniform samplerBuffer g_sampler;" NL "void main() {" NL "  vec4 pi = imageLoad(g_image, gl_VertexID);" NL
5107			"  vec4 ps = texelFetch(g_sampler, gl_VertexID);" NL
5108			"  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
5109			"  gl_Position = pi;" NL "}";
5110		const char* const glsl_draw_fs =
5111			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5112			"  o_color = vs_color;" NL "}";
5113		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5114		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5115
5116		glGenVertexArrays(1, &m_attribless_vao);
5117		glBindVertexArray(m_attribless_vao);
5118
5119		glGenBuffers(1, &m_buffer);
5120		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5121		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5122		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5123
5124		glGenTextures(1, &m_buffer_tex);
5125		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5126		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_buffer);
5127
5128		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
5129
5130		glEnable(GL_RASTERIZER_DISCARD);
5131		glUseProgram(m_store_program);
5132		glDrawArrays(GL_POINTS, 0, 4);
5133
5134		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT);
5135
5136		glDisable(GL_RASTERIZER_DISCARD);
5137		glClear(GL_COLOR_BUFFER_BIT);
5138		glUseProgram(m_draw_program);
5139		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5140
5141		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5142		{
5143			return ERROR;
5144		}
5145		return NO_ERROR;
5146	}
5147
5148	virtual long Cleanup()
5149	{
5150		glUseProgram(0);
5151		glDeleteBuffers(1, &m_buffer);
5152		glDeleteTextures(1, &m_buffer_tex);
5153		glDeleteProgram(m_store_program);
5154		glDeleteProgram(m_draw_program);
5155		glDeleteVertexArrays(1, &m_attribless_vao);
5156		return NO_ERROR;
5157	}
5158};
5159//-----------------------------------------------------------------------------
5160// 2.1.2 AdvancedSyncVertexArray
5161//-----------------------------------------------------------------------------
5162class AdvancedSyncVertexArray : public ShaderImageLoadStoreBase
5163{
5164	GLuint m_position_buffer;
5165	GLuint m_color_buffer;
5166	GLuint m_element_buffer;
5167	GLuint m_position_buffer_tex;
5168	GLuint m_color_buffer_tex;
5169	GLuint m_element_buffer_tex;
5170	GLuint m_store_program;
5171	GLuint m_draw_program;
5172	GLuint m_attribless_vao;
5173	GLuint m_draw_vao;
5174
5175	virtual long Setup()
5176	{
5177		m_position_buffer	 = 0;
5178		m_color_buffer		  = 0;
5179		m_element_buffer	  = 0;
5180		m_position_buffer_tex = 0;
5181		m_color_buffer_tex	= 0;
5182		m_element_buffer_tex  = 0;
5183		m_store_program		  = 0;
5184		m_draw_program		  = 0;
5185		m_attribless_vao	  = 0;
5186		m_draw_vao			  = 0;
5187		return NO_ERROR;
5188	}
5189
5190	virtual long Run()
5191	{
5192		if (!SupportedInVS(3))
5193			return NOT_SUPPORTED;
5194		const char* const glsl_store_vs =
5195			"#version 420 core" NL "layout(rg32f) writeonly uniform imageBuffer g_position_buffer;" NL
5196			"layout(rgba32f) writeonly uniform imageBuffer g_color_buffer;" NL
5197			"layout(r32ui) writeonly uniform uimageBuffer g_element_buffer;" NL "uniform vec4 g_color;" NL
5198			"void main() {" NL "  vec2[4] data = vec2[4](vec2(-1, -1), vec2(1, -1), vec2(-1, 1), vec2(1, 1));" NL
5199			"  imageStore(g_position_buffer, gl_VertexID, vec4(data[gl_VertexID], 0.0, 1.0));" NL
5200			"  imageStore(g_color_buffer, gl_VertexID, g_color);" NL
5201			"  imageStore(g_element_buffer, gl_VertexID, uvec4(gl_VertexID));" NL "}";
5202		const char* const glsl_draw_vs =
5203			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5204			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL "void main() {" NL
5205			"  gl_Position = i_position;" NL "  vs_color = i_color;" NL "}";
5206		const char* const glsl_draw_fs =
5207			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL "void main() {" NL
5208			"  o_color = vs_color;" NL "}";
5209		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5210		glUseProgram(m_store_program);
5211		glUniform1i(glGetUniformLocation(m_store_program, "g_position_buffer"), 0);
5212		glUniform1i(glGetUniformLocation(m_store_program, "g_color_buffer"), 1);
5213		glUniform1i(glGetUniformLocation(m_store_program, "g_element_buffer"), 2);
5214		glUseProgram(0);
5215
5216		m_draw_program = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5217
5218		glGenBuffers(1, &m_position_buffer);
5219		glBindBuffer(GL_TEXTURE_BUFFER, m_position_buffer);
5220		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec2) * 4, NULL, GL_DYNAMIC_DRAW);
5221		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5222
5223		glGenBuffers(1, &m_color_buffer);
5224		glBindBuffer(GL_TEXTURE_BUFFER, m_color_buffer);
5225		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_DYNAMIC_DRAW);
5226		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5227
5228		glGenBuffers(1, &m_element_buffer);
5229		glBindBuffer(GL_TEXTURE_BUFFER, m_element_buffer);
5230		glBufferData(GL_TEXTURE_BUFFER, sizeof(GLuint) * 4, NULL, GL_DYNAMIC_DRAW);
5231		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5232
5233		glGenTextures(1, &m_position_buffer_tex);
5234		glBindTexture(GL_TEXTURE_BUFFER, m_position_buffer_tex);
5235		glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32F, m_position_buffer);
5236		glBindTexture(GL_TEXTURE_BUFFER, 0);
5237
5238		glGenTextures(1, &m_color_buffer_tex);
5239		glBindTexture(GL_TEXTURE_BUFFER, m_color_buffer_tex);
5240		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_color_buffer);
5241		glBindTexture(GL_TEXTURE_BUFFER, 0);
5242
5243		glGenTextures(1, &m_element_buffer_tex);
5244		glBindTexture(GL_TEXTURE_BUFFER, m_element_buffer_tex);
5245		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, m_element_buffer);
5246		glBindTexture(GL_TEXTURE_BUFFER, 0);
5247
5248		glGenVertexArrays(1, &m_attribless_vao);
5249
5250		glGenVertexArrays(1, &m_draw_vao);
5251		glBindVertexArray(m_draw_vao);
5252		glBindBuffer(GL_ARRAY_BUFFER, m_position_buffer);
5253		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
5254		glBindBuffer(GL_ARRAY_BUFFER, m_color_buffer);
5255		glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
5256		glBindBuffer(GL_ARRAY_BUFFER, 0);
5257		glEnableVertexAttribArray(0);
5258		glEnableVertexAttribArray(1);
5259		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_element_buffer);
5260		glBindVertexArray(0);
5261
5262		glEnable(GL_RASTERIZER_DISCARD);
5263		glBindImageTexture(0, m_position_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RG32F);
5264		glBindImageTexture(1, m_color_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5265		glBindImageTexture(2, m_element_buffer_tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32UI);
5266		glUseProgram(m_store_program);
5267		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5268		glBindVertexArray(m_attribless_vao);
5269		glDrawArrays(GL_POINTS, 0, 4);
5270
5271		glDisable(GL_RASTERIZER_DISCARD);
5272		glClear(GL_COLOR_BUFFER_BIT);
5273		glUseProgram(m_draw_program);
5274		glBindVertexArray(m_draw_vao);
5275		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5276		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5277
5278		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5279		{
5280			return ERROR;
5281		}
5282
5283		glEnable(GL_RASTERIZER_DISCARD);
5284		glUseProgram(m_store_program);
5285		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 0.0f, 1.0f, 1.0f);
5286		glBindVertexArray(m_attribless_vao);
5287		glDrawArrays(GL_POINTS, 0, 4);
5288
5289		glDisable(GL_RASTERIZER_DISCARD);
5290		glClear(GL_COLOR_BUFFER_BIT);
5291		glUseProgram(m_draw_program);
5292		glBindVertexArray(m_draw_vao);
5293		glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT);
5294		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
5295
5296		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 0, 1, 1)))
5297		{
5298			return ERROR;
5299		}
5300		return NO_ERROR;
5301	}
5302
5303	virtual long Cleanup()
5304	{
5305		glDisable(GL_RASTERIZER_DISCARD);
5306		glUseProgram(0);
5307		glDeleteBuffers(1, &m_position_buffer);
5308		glDeleteBuffers(1, &m_color_buffer);
5309		glDeleteBuffers(1, &m_element_buffer);
5310		glDeleteTextures(1, &m_position_buffer_tex);
5311		glDeleteTextures(1, &m_color_buffer_tex);
5312		glDeleteTextures(1, &m_element_buffer_tex);
5313		glDeleteProgram(m_store_program);
5314		glDeleteProgram(m_draw_program);
5315		glDeleteVertexArrays(1, &m_attribless_vao);
5316		glDeleteVertexArrays(1, &m_draw_vao);
5317		return NO_ERROR;
5318	}
5319};
5320
5321//-----------------------------------------------------------------------------
5322// 2.1.4 AdvancedSyncDrawIndirect
5323//-----------------------------------------------------------------------------
5324class AdvancedSyncDrawIndirect : public ShaderImageLoadStoreBase
5325{
5326	GLuint m_draw_command_buffer;
5327	GLuint m_draw_command_buffer_tex;
5328	GLuint m_store_program;
5329	GLuint m_draw_program;
5330	GLuint m_attribless_vao;
5331	GLuint m_draw_vao;
5332	GLuint m_draw_vbo;
5333
5334	virtual long Setup()
5335	{
5336		m_draw_command_buffer	 = 0;
5337		m_draw_command_buffer_tex = 0;
5338		m_store_program			  = 0;
5339		m_draw_program			  = 0;
5340		m_attribless_vao		  = 0;
5341		m_draw_vao				  = 0;
5342		m_draw_vbo				  = 0;
5343		return NO_ERROR;
5344	}
5345
5346	virtual long Run()
5347	{
5348		if (!SupportedInVS(1))
5349			return NOT_SUPPORTED;
5350		const char* const glsl_store_vs =
5351			"#version 420 core" NL "writeonly uniform uimageBuffer g_draw_command_buffer;" NL "void main() {" NL
5352			"  imageStore(g_draw_command_buffer, 0, uvec4(4, 1, 0, 0));" NL "}";
5353		const char* const glsl_draw_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5354										 "void main() {" NL "  gl_Position = i_position;" NL "}";
5355		const char* const glsl_draw_fs = "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5356										 "void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5357		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5358		m_draw_program  = BuildProgram(glsl_draw_vs, NULL, NULL, NULL, glsl_draw_fs);
5359
5360		glGenBuffers(1, &m_draw_command_buffer);
5361		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5362		glBufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(uvec4), NULL, GL_DYNAMIC_DRAW);
5363		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
5364
5365		glGenTextures(1, &m_draw_command_buffer_tex);
5366		glBindTexture(GL_TEXTURE_BUFFER, m_draw_command_buffer_tex);
5367		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, m_draw_command_buffer);
5368		glBindTexture(GL_TEXTURE_BUFFER, 0);
5369
5370		glGenVertexArrays(1, &m_attribless_vao);
5371		CreateFullViewportQuad(&m_draw_vao, &m_draw_vbo, NULL);
5372
5373		glBindImageTexture(0, m_draw_command_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
5374
5375		glEnable(GL_RASTERIZER_DISCARD);
5376		glUseProgram(m_store_program);
5377		glBindVertexArray(m_attribless_vao);
5378		glDrawArrays(GL_POINTS, 0, 1);
5379
5380		glDisable(GL_RASTERIZER_DISCARD);
5381		glClear(GL_COLOR_BUFFER_BIT);
5382		glUseProgram(m_draw_program);
5383		glBindVertexArray(m_draw_vao);
5384		glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_draw_command_buffer);
5385		glMemoryBarrier(GL_COMMAND_BARRIER_BIT);
5386		glDrawArraysIndirect(GL_TRIANGLE_STRIP, 0);
5387
5388		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5389		{
5390			return ERROR;
5391		}
5392		return NO_ERROR;
5393	}
5394
5395	virtual long Cleanup()
5396	{
5397		glUseProgram(0);
5398		glDeleteBuffers(1, &m_draw_command_buffer);
5399		glDeleteTextures(1, &m_draw_command_buffer_tex);
5400		glDeleteProgram(m_store_program);
5401		glDeleteProgram(m_draw_program);
5402		glDeleteVertexArrays(1, &m_attribless_vao);
5403		glDeleteVertexArrays(1, &m_draw_vao);
5404		glDeleteBuffers(1, &m_draw_vbo);
5405		return NO_ERROR;
5406	}
5407};
5408//-----------------------------------------------------------------------------
5409// 2.1.5 AdvancedSyncTextureUpdate
5410//-----------------------------------------------------------------------------
5411class AdvancedSyncTextureUpdate : public ShaderImageLoadStoreBase
5412{
5413	GLuint m_texture;
5414	GLuint m_store_program;
5415	GLuint m_draw_program;
5416	GLuint m_vao;
5417	GLuint m_vbo;
5418	GLuint m_pbo;
5419
5420	virtual long Setup()
5421	{
5422		m_texture		= 0;
5423		m_store_program = 0;
5424		m_draw_program  = 0;
5425		m_vao			= 0;
5426		m_vbo			= 0;
5427		m_pbo			= 0;
5428		return NO_ERROR;
5429	}
5430
5431	virtual long Run()
5432	{
5433		const char* const glsl_vs =
5434			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5435			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5436		const char* const glsl_store_fs =
5437			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
5438			"  imageStore(g_image, ivec2(gl_FragCoord.xy), gl_FragCoord);" NL "  discard;" NL "}";
5439		const char* const glsl_draw_fs =
5440			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5441			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5442		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5443		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5444
5445		std::vector<vec4> data(16 * 16, vec4(1.0f));
5446		glGenBuffers(1, &m_pbo);
5447		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5448		glBufferData(GL_PIXEL_UNPACK_BUFFER, 16 * 16 * sizeof(vec4), &data[0], GL_DYNAMIC_READ);
5449		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5450
5451		glGenTextures(1, &m_texture);
5452		glBindTexture(GL_TEXTURE_2D, m_texture);
5453		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5454		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
5455		glBindTexture(GL_TEXTURE_2D, 0);
5456
5457		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5458
5459		glViewport(0, 0, 16, 16);
5460		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5461		glUseProgram(m_store_program);
5462		glBindVertexArray(m_vao);
5463		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5464
5465		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
5466		glBindTexture(GL_TEXTURE_2D, m_texture);
5467		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
5468		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_FLOAT, 0);
5469		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
5470
5471		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5472		glClear(GL_COLOR_BUFFER_BIT);
5473		glUseProgram(m_draw_program);
5474		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5475
5476		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(1, 1, 1, 1)))
5477		{
5478			return ERROR;
5479		}
5480		return NO_ERROR;
5481	}
5482
5483	virtual long Cleanup()
5484	{
5485		glUseProgram(0);
5486		glDeleteBuffers(1, &m_vbo);
5487		glDeleteBuffers(1, &m_pbo);
5488		glDeleteTextures(1, &m_texture);
5489		glDeleteProgram(m_store_program);
5490		glDeleteProgram(m_draw_program);
5491		glDeleteVertexArrays(1, &m_vao);
5492		return NO_ERROR;
5493	}
5494};
5495//-----------------------------------------------------------------------------
5496// 2.1.6 AdvancedSyncImageAccess2
5497//-----------------------------------------------------------------------------
5498class AdvancedSyncImageAccess2 : public ShaderImageLoadStoreBase
5499{
5500	GLuint m_texture;
5501	GLuint m_store_program;
5502	GLuint m_draw_program;
5503	GLuint m_vao;
5504	GLuint m_vbo;
5505
5506	virtual long Setup()
5507	{
5508		m_texture		= 0;
5509		m_store_program = 0;
5510		m_draw_program  = 0;
5511		m_vao			= 0;
5512		m_vbo			= 0;
5513		return NO_ERROR;
5514	}
5515
5516	virtual long Run()
5517	{
5518		const char* const glsl_vs =
5519			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec2 vs_texcoord;" NL
5520			"void main() {" NL "  gl_Position = i_position;" NL "  vs_texcoord = 0.5 + 0.5 * i_position.xy;" NL "}";
5521		const char* const glsl_store_fs =
5522			"#version 420 core" NL "writeonly uniform image2D g_image;" NL "uniform vec4 g_color;" NL "void main() {" NL
5523			"  imageStore(g_image, ivec2(gl_FragCoord.xy), g_color);" NL "  discard;" NL "}";
5524		const char* const glsl_draw_fs =
5525			"#version 420 core" NL "in vec2 vs_texcoord;" NL "layout(location = 0) out vec4 o_color;" NL
5526			"uniform sampler2D g_sampler;" NL "void main() {" NL "  o_color = texture(g_sampler, vs_texcoord);" NL "}";
5527		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
5528		m_draw_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_draw_fs);
5529
5530		int width  = getWindowWidth();
5531		int height = getWindowHeight();
5532		scaleDimensionsToMemory(width, height, 1, 1, 16, 16);
5533
5534		glGenTextures(1, &m_texture);
5535		glBindTexture(GL_TEXTURE_2D, m_texture);
5536		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5537		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
5538		glBindTexture(GL_TEXTURE_2D, 0);
5539
5540		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5541
5542		glViewport(0, 0, width, height);
5543		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
5544		glUseProgram(m_store_program);
5545		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 1.0f, 0.0f, 0.0f, 1.0f);
5546		glBindVertexArray(m_vao);
5547		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5548
5549		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
5550
5551		glUniform4f(glGetUniformLocation(m_store_program, "g_color"), 0.0f, 1.0f, 0.0f, 1.0f);
5552		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5553
5554		glClear(GL_COLOR_BUFFER_BIT);
5555		glBindTexture(GL_TEXTURE_2D, m_texture);
5556		glUseProgram(m_draw_program);
5557		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
5558
5559		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5560		{
5561			return ERROR;
5562		}
5563		return NO_ERROR;
5564	}
5565
5566	virtual long Cleanup()
5567	{
5568		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5569		glUseProgram(0);
5570		glDeleteBuffers(1, &m_vbo);
5571		glDeleteTextures(1, &m_texture);
5572		glDeleteProgram(m_store_program);
5573		glDeleteProgram(m_draw_program);
5574		glDeleteVertexArrays(1, &m_vao);
5575		return NO_ERROR;
5576	}
5577};
5578//-----------------------------------------------------------------------------
5579// 2.1.7 AdvancedSyncBufferUpdate
5580//-----------------------------------------------------------------------------
5581class AdvancedSyncBufferUpdate : public ShaderImageLoadStoreBase
5582{
5583	GLuint m_buffer;
5584	GLuint m_buffer_tex;
5585	GLuint m_store_program;
5586	GLuint m_attribless_vao;
5587
5588	virtual long Setup()
5589	{
5590		m_buffer		 = 0;
5591		m_buffer_tex	 = 0;
5592		m_store_program  = 0;
5593		m_attribless_vao = 0;
5594		return NO_ERROR;
5595	}
5596
5597	virtual long Run()
5598	{
5599		if (!SupportedInVS(1))
5600			return NOT_SUPPORTED;
5601		const char* const glsl_store_vs =
5602			"#version 420 core" NL "writeonly uniform imageBuffer g_output_data;" NL "void main() {" NL
5603			"  imageStore(g_output_data, gl_VertexID, vec4(gl_VertexID));" NL "}";
5604		m_store_program = BuildProgram(glsl_store_vs, NULL, NULL, NULL, NULL);
5605
5606		glGenVertexArrays(1, &m_attribless_vao);
5607		glBindVertexArray(m_attribless_vao);
5608
5609		glGenBuffers(1, &m_buffer);
5610		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5611		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 1000, NULL, GL_DYNAMIC_DRAW);
5612		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5613
5614		glGenTextures(1, &m_buffer_tex);
5615		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5616		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5617
5618		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5619
5620		glEnable(GL_RASTERIZER_DISCARD);
5621		glUseProgram(m_store_program);
5622		glDrawArrays(GL_POINTS, 0, 1000);
5623
5624		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5625
5626		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5627		vec4* ptr =
5628			reinterpret_cast<vec4*>(glMapBufferRange(GL_TEXTURE_BUFFER, 0, 1000 * sizeof(vec4), GL_MAP_READ_BIT));
5629		for (int i = 0; i < 1000; ++i)
5630		{
5631			if (!IsEqual(ptr[i], vec4(static_cast<float>(i))))
5632			{
5633				m_context.getTestContext().getLog()
5634					<< tcu::TestLog::Message << "Bad buffer value found at index " << i << tcu::TestLog::EndMessage;
5635				return ERROR;
5636			}
5637		}
5638		return NO_ERROR;
5639	}
5640
5641	virtual long Cleanup()
5642	{
5643		glDisable(GL_RASTERIZER_DISCARD);
5644		glUseProgram(0);
5645		glDeleteBuffers(1, &m_buffer);
5646		glDeleteTextures(1, &m_buffer_tex);
5647		glDeleteProgram(m_store_program);
5648		glDeleteVertexArrays(1, &m_attribless_vao);
5649		return NO_ERROR;
5650	}
5651};
5652//-----------------------------------------------------------------------------
5653// 2.2.1 AdvancedAllStagesOneImage
5654//-----------------------------------------------------------------------------
5655class AdvancedAllStagesOneImage : public ShaderImageLoadStoreBase
5656{
5657	GLuint m_program;
5658	GLuint m_vao;
5659	GLuint m_vbo;
5660	GLuint m_ebo;
5661	GLuint m_buffer;
5662	GLuint m_buffer_tex;
5663	GLuint m_texture;
5664
5665	virtual long Setup()
5666	{
5667		m_program	= 0;
5668		m_vao		 = 0;
5669		m_vbo		 = 0;
5670		m_ebo		 = 0;
5671		m_buffer	 = 0;
5672		m_buffer_tex = 0;
5673		m_texture	= 0;
5674		return NO_ERROR;
5675	}
5676
5677	virtual long Run()
5678	{
5679		if (!SupportedInGeomStages(2))
5680			return NOT_SUPPORTED;
5681		const char* const glsl_vs =
5682			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5683			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5684			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5685			"  gl_Position = i_position + vec4(1.0, 1.0, 0.0, 0.0);" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5686			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5687		const char* const glsl_tcs =
5688			"#version 420 core" NL "layout(vertices = 1) out;" NL
5689			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5690			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5691			"  gl_out[gl_InvocationID].gl_Position = gl_in[0].gl_Position;" NL "  gl_TessLevelInner[0] = 1.0;" NL
5692			"  gl_TessLevelInner[1] = 1.0;" NL "  gl_TessLevelOuter[0] = 1.0;" NL "  gl_TessLevelOuter[1] = 1.0;" NL
5693			"  gl_TessLevelOuter[2] = 1.0;" NL "  gl_TessLevelOuter[3] = 1.0;" NL "  imageAtomicAdd(g_buffer, 0, 1);" NL
5694			"  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL "}";
5695		const char* const glsl_tes =
5696			"#version 420 core" NL "layout(triangles, point_mode) in;" NL
5697			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5698			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5699			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5700			"  gl_Position = gl_in[0].gl_Position;" NL "}";
5701		const char* const glsl_gs =
5702			"#version 420 core" NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL
5703			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5704			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5705			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5706			"  gl_Position = gl_in[0].gl_Position;" NL "  EmitVertex();" NL "}";
5707		const char* const glsl_fs =
5708			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
5709			"layout(r32i) coherent uniform iimageBuffer g_buffer;" NL
5710			"layout(r32ui) coherent uniform uimage2D g_image;" NL "void main() {" NL
5711			"  imageAtomicAdd(g_buffer, 0, 1);" NL "  imageAtomicAdd(g_image, ivec2(0, 0), 2u);" NL
5712			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "}";
5713		m_program = BuildProgram(glsl_vs, glsl_tcs, glsl_tes, glsl_gs, glsl_fs);
5714		glUseProgram(m_program);
5715		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5716		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5717
5718		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
5719
5720		GLint i32 = 0;
5721		glGenBuffers(1, &m_buffer);
5722		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5723		glBufferData(GL_TEXTURE_BUFFER, 4, &i32, GL_STATIC_DRAW);
5724		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5725
5726		glGenTextures(1, &m_buffer_tex);
5727		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5728		glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, m_buffer);
5729		glBindTexture(GL_TEXTURE_BUFFER, 0);
5730
5731		GLuint ui32 = 0;
5732		glGenTextures(1, &m_texture);
5733		glBindTexture(GL_TEXTURE_2D, m_texture);
5734		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5735		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5736		glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 1, 1, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5737		glBindTexture(GL_TEXTURE_2D, 0);
5738
5739		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
5740		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
5741
5742		glBindVertexArray(m_vao);
5743		glPatchParameteri(GL_PATCH_VERTICES, 1);
5744
5745		glDrawElementsInstancedBaseVertex(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1, 0);
5746		glDrawElementsInstanced(GL_PATCHES, 1, GL_UNSIGNED_SHORT, 0, 1);
5747
5748		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
5749		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5750		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, 4, &i32);
5751		if (i32 < 20 || i32 > 50)
5752		{
5753			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Buffer value is " << i32
5754												<< " should be in the range [20;50]" << tcu::TestLog::EndMessage;
5755			return ERROR;
5756		}
5757
5758		glBindTexture(GL_TEXTURE_2D, m_texture);
5759		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, &ui32);
5760		if (ui32 < 40 || ui32 != static_cast<GLuint>(2 * i32))
5761		{
5762			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texture value is " << ui32 << " should be "
5763												<< (2 * i32) << tcu::TestLog::EndMessage;
5764			return ERROR;
5765		}
5766
5767		return NO_ERROR;
5768	}
5769
5770	virtual long Cleanup()
5771	{
5772		glPatchParameteri(GL_PATCH_VERTICES, 3);
5773		glUseProgram(0);
5774		glDeleteBuffers(1, &m_buffer);
5775		glDeleteBuffers(1, &m_vbo);
5776		glDeleteBuffers(1, &m_ebo);
5777		glDeleteTextures(1, &m_buffer_tex);
5778		glDeleteTextures(1, &m_texture);
5779		glDeleteProgram(m_program);
5780		glDeleteVertexArrays(1, &m_vao);
5781		return NO_ERROR;
5782	}
5783};
5784//-----------------------------------------------------------------------------
5785// 2.3.1 AdvancedMemoryDependentInvocation
5786//-----------------------------------------------------------------------------
5787class AdvancedMemoryDependentInvocation : public ShaderImageLoadStoreBase
5788{
5789	GLuint m_buffer;
5790	GLuint m_buffer_tex;
5791	GLuint m_texture;
5792	GLuint m_program;
5793	GLuint m_vao;
5794	GLuint m_vbo;
5795
5796	virtual long Setup()
5797	{
5798		m_buffer	 = 0;
5799		m_buffer_tex = 0;
5800		m_texture	= 0;
5801		m_program	= 0;
5802		m_vao		 = 0;
5803		m_vbo		 = 0;
5804		return NO_ERROR;
5805	}
5806
5807	virtual long Run()
5808	{
5809		if (!SupportedInVS(2))
5810			return NOT_SUPPORTED;
5811		const char* const glsl_vs =
5812			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
5813			"layout(location = 1) in vec4 i_color;" NL "out vec4 vs_color;" NL
5814			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5815			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  gl_Position = i_position;" NL
5816			"  vs_color = i_color;" NL "  imageStore(g_buffer, 0, vec4(1.0));" NL
5817			"  imageStore(g_image, ivec2(0, 0), vec4(2.0));" NL "  memoryBarrier();" NL "}";
5818		const char* const glsl_fs =
5819			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5820			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL
5821			"layout(rgba32f) coherent uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5822			"  if (imageLoad(g_buffer, 0) != vec4(1.0)) o_color = vec4(1.0, 0.0, 0.0, 0.1);" NL
5823			"  if (imageLoad(g_image, ivec2(0, 0)) != vec4(2.0)) o_color = vec4(1.0, 0.0, 0.0, 0.2);" NL "}";
5824		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5825		glUseProgram(m_program);
5826		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5827		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5828
5829		vec4 zero(0);
5830		glGenBuffers(1, &m_buffer);
5831		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5832		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4), &zero, GL_STATIC_DRAW);
5833		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5834
5835		glGenTextures(1, &m_buffer_tex);
5836		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5837		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5838		glBindTexture(GL_TEXTURE_BUFFER, 0);
5839
5840		glGenTextures(1, &m_texture);
5841		glBindTexture(GL_TEXTURE_2D, m_texture);
5842		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5843		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, &zero);
5844		glBindTexture(GL_TEXTURE_2D, 0);
5845
5846		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5847		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5848
5849		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5850
5851		glClear(GL_COLOR_BUFFER_BIT);
5852		glBindVertexArray(m_vao);
5853		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5854
5855		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
5856		{
5857			return ERROR;
5858		}
5859		return NO_ERROR;
5860	}
5861
5862	virtual long Cleanup()
5863	{
5864		glUseProgram(0);
5865		glDeleteBuffers(1, &m_vbo);
5866		glDeleteBuffers(1, &m_buffer);
5867		glDeleteTextures(1, &m_texture);
5868		glDeleteTextures(1, &m_buffer_tex);
5869		glDeleteProgram(m_program);
5870		glDeleteVertexArrays(1, &m_vao);
5871		return NO_ERROR;
5872	}
5873};
5874//-----------------------------------------------------------------------------
5875// 2.3.2 AdvancedMemoryOrder
5876//-----------------------------------------------------------------------------
5877class AdvancedMemoryOrder : public ShaderImageLoadStoreBase
5878{
5879	GLuint m_buffer;
5880	GLuint m_buffer_tex;
5881	GLuint m_texture;
5882	GLuint m_program;
5883	GLuint m_vao;
5884	GLuint m_vbo;
5885
5886	virtual long Setup()
5887	{
5888		m_buffer	 = 0;
5889		m_buffer_tex = 0;
5890		m_texture	= 0;
5891		m_program	= 0;
5892		m_vao		 = 0;
5893		m_vbo		 = 0;
5894		return NO_ERROR;
5895	}
5896
5897	virtual long Run()
5898	{
5899		if (!SupportedInVS(1))
5900			return NOT_SUPPORTED;
5901		const char* const glsl_vs =
5902			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out vec4 vs_color;" NL
5903			"layout(rgba32f) coherent uniform imageBuffer g_buffer;" NL "void main() {" NL
5904			"  gl_Position = i_position;" NL "  vs_color = vec4(0, 1, 0, 1);" NL
5905			"  imageStore(g_buffer, gl_VertexID, vec4(1.0));" NL "  imageStore(g_buffer, gl_VertexID, vec4(2.0));" NL
5906			"  imageStore(g_buffer, gl_VertexID, vec4(3.0));" NL
5907			"  if (imageLoad(g_buffer, gl_VertexID) != vec4(3.0)) vs_color = vec4(1, 0, 0, 1);" NL "}";
5908		const char* const glsl_fs =
5909			"#version 420 core" NL "in vec4 vs_color;" NL "layout(location = 0) out vec4 o_color;" NL
5910			"layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL "  o_color = vs_color;" NL
5911			"  ivec2 coord = ivec2(gl_FragCoord);" NL "  for (int i = 0; i < 3; ++i) {" NL
5912			"    imageStore(g_image, coord, vec4(i));" NL "    vec4 v = imageLoad(g_image, coord);" NL
5913			"    if (v != vec4(i)) {" NL "      o_color = vec4(v.xyz, 0.0);" NL "      break;" NL "    }" NL "  }" NL
5914			"}";
5915		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
5916		glUseProgram(m_program);
5917		glUniform1i(glGetUniformLocation(m_program, "g_buffer"), 0);
5918		glUniform1i(glGetUniformLocation(m_program, "g_image"), 1);
5919
5920		glGenBuffers(1, &m_buffer);
5921		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
5922		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
5923		glBindBuffer(GL_TEXTURE_BUFFER, 0);
5924
5925		glGenTextures(1, &m_buffer_tex);
5926		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
5927		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
5928		glBindTexture(GL_TEXTURE_BUFFER, 0);
5929
5930		int width  = getWindowWidth();
5931		int height = getWindowHeight();
5932		scaleDimensionsToMemory(width, height, 1, 2, 16, 16);
5933
5934		std::vector<vec4> data(width * height);
5935		glGenTextures(1, &m_texture);
5936		glBindTexture(GL_TEXTURE_2D, m_texture);
5937		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5938		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
5939		glBindTexture(GL_TEXTURE_2D, 0);
5940
5941		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5942		glBindImageTexture(1, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
5943
5944		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5945
5946		glClear(GL_COLOR_BUFFER_BIT);
5947		glViewport(0, 0, width, height);
5948		glBindVertexArray(m_vao);
5949		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
5950
5951		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
5952		{
5953			return ERROR;
5954		}
5955		return NO_ERROR;
5956	}
5957
5958	virtual long Cleanup()
5959	{
5960		glViewport(0, 0, getWindowWidth(), getWindowHeight());
5961		glUseProgram(0);
5962		glDeleteBuffers(1, &m_vbo);
5963		glDeleteBuffers(1, &m_buffer);
5964		glDeleteTextures(1, &m_texture);
5965		glDeleteTextures(1, &m_buffer_tex);
5966		glDeleteProgram(m_program);
5967		glDeleteVertexArrays(1, &m_vao);
5968		return NO_ERROR;
5969	}
5970};
5971//-----------------------------------------------------------------------------
5972// 2.4.1 AdvancedSSOSimple
5973//-----------------------------------------------------------------------------
5974class AdvancedSSOSimple : public ShaderImageLoadStoreBase
5975{
5976	GLuint m_texture;
5977	GLuint m_pipeline[2];
5978	GLuint m_vsp, m_fsp0, m_fsp1;
5979	GLuint m_vao, m_vbo;
5980
5981	virtual long Setup()
5982	{
5983		glGenTextures(1, &m_texture);
5984		glGenProgramPipelines(2, m_pipeline);
5985		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
5986
5987		const char* const glsl_vs =
5988			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
5989			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
5990		const char* const glsl_fs0 =
5991			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[4];" NL "void main() {" NL
5992			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5993			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(1.0));" NL "  }" NL "  discard;" NL "}";
5994		const char* const glsl_fs1 =
5995			"#version 420 core" NL "writeonly uniform image2D g_image[4];" NL "void main() {" NL
5996			"  for (int i = 0; i < g_image.length(); ++i) {" NL
5997			"    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(2.0));" NL "  }" NL "  discard;" NL "}";
5998		m_vsp  = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
5999		m_fsp0 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs0);
6000		m_fsp1 = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs1);
6001
6002		return NO_ERROR;
6003	}
6004
6005	virtual long Run()
6006	{
6007		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[0]"), 0);
6008		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[1]"), 2);
6009		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[2]"), 4);
6010		glProgramUniform1i(m_fsp0, glGetUniformLocation(m_fsp0, "g_image[3]"), 6);
6011
6012		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[0]"), 1);
6013		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[1]"), 3);
6014		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[2]"), 5);
6015		glProgramUniform1i(m_fsp1, glGetUniformLocation(m_fsp1, "g_image[3]"), 7);
6016
6017		glUseProgramStages(m_pipeline[0], GL_VERTEX_SHADER_BIT, m_vsp);
6018		glUseProgramStages(m_pipeline[0], GL_FRAGMENT_SHADER_BIT, m_fsp0);
6019
6020		glUseProgramStages(m_pipeline[1], GL_VERTEX_SHADER_BIT, m_vsp);
6021		glUseProgramStages(m_pipeline[1], GL_FRAGMENT_SHADER_BIT, m_fsp1);
6022
6023		int width  = getWindowWidth();
6024		int height = getWindowHeight();
6025		scaleDimensionsToMemory(width, height, 8, 8, 16, 16);
6026
6027		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6028		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6029		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6030
6031		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6032		glBindImageTexture(1, m_texture, 0, GL_FALSE, 1, GL_READ_WRITE, GL_RGBA32F);
6033		glBindImageTexture(2, m_texture, 0, GL_FALSE, 2, GL_READ_WRITE, GL_RGBA32F);
6034		glBindImageTexture(3, m_texture, 0, GL_FALSE, 3, GL_READ_WRITE, GL_RGBA32F);
6035		glBindImageTexture(4, m_texture, 0, GL_FALSE, 4, GL_READ_WRITE, GL_RGBA32F);
6036		glBindImageTexture(5, m_texture, 0, GL_FALSE, 5, GL_READ_WRITE, GL_RGBA32F);
6037		glBindImageTexture(6, m_texture, 0, GL_FALSE, 6, GL_READ_WRITE, GL_RGBA32F);
6038		glBindImageTexture(7, m_texture, 0, GL_FALSE, 7, GL_READ_WRITE, GL_RGBA32F);
6039
6040		glBindVertexArray(m_vao);
6041
6042		glViewport(0, 0, width, height);
6043		glBindProgramPipeline(m_pipeline[0]);
6044		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6045
6046		glBindProgramPipeline(m_pipeline[1]);
6047		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
6048
6049		std::vector<vec4> data(width * height * 8);
6050		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6051
6052		for (int layer = 0; layer < 8; ++layer)
6053		{
6054			for (int h = 0; h < height; ++h)
6055			{
6056				for (int w = 0; w < width; ++w)
6057				{
6058					const vec4 c = data[layer * width * height + h * width + w];
6059					if (layer % 2)
6060					{
6061						if (!IsEqual(c, vec4(2.0f)))
6062						{
6063							return ERROR;
6064						}
6065					}
6066					else
6067					{
6068						if (!IsEqual(c, vec4(1.0f)))
6069						{
6070							return ERROR;
6071						}
6072					}
6073				}
6074			}
6075		}
6076		return NO_ERROR;
6077	}
6078
6079	virtual long Cleanup()
6080	{
6081		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6082		glDeleteBuffers(1, &m_vbo);
6083		glDeleteTextures(1, &m_texture);
6084		glDeleteProgram(m_vsp);
6085		glDeleteProgram(m_fsp0);
6086		glDeleteProgram(m_fsp1);
6087		glDeleteVertexArrays(1, &m_vao);
6088		glDeleteProgramPipelines(2, m_pipeline);
6089		return NO_ERROR;
6090	}
6091};
6092//-----------------------------------------------------------------------------
6093// 2.4.2 AdvancedSSOAtomicCounters
6094//-----------------------------------------------------------------------------
6095class AdvancedSSOAtomicCounters : public ShaderImageLoadStoreBase
6096{
6097	GLuint m_buffer, m_buffer_tex;
6098	GLuint m_counter_buffer;
6099	GLuint m_transform_buffer;
6100	GLuint m_pipeline;
6101	GLuint m_vao, m_vbo;
6102	GLuint m_vsp, m_fsp;
6103
6104	virtual long Setup()
6105	{
6106		m_vao = 0;
6107		m_vbo = 0;
6108		m_vsp = 0;
6109		m_fsp = 0;
6110		glGenBuffers(1, &m_buffer);
6111		glGenTextures(1, &m_buffer_tex);
6112		glGenBuffers(1, &m_counter_buffer);
6113		glGenBuffers(1, &m_transform_buffer);
6114		glGenProgramPipelines(1, &m_pipeline);
6115		return NO_ERROR;
6116	}
6117
6118	virtual long Run()
6119	{
6120		if (!SupportedInVS(1))
6121			return NOT_SUPPORTED;
6122
6123		CreateFullViewportQuad(&m_vao, &m_vbo, NULL);
6124		const char* const glsl_vs =
6125			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6126			"layout(location = 1) in vec4 i_color;" NL "layout(location = 3) out vec4 o_color;" NL
6127			"out gl_PerVertex {" NL "  vec4 gl_Position;" NL "};" NL "layout(std140) uniform Transform {" NL
6128			"  mat4 mvp;" NL "} g_transform;" NL "writeonly uniform imageBuffer g_buffer;" NL
6129			"layout(binding = 0, offset = 0) uniform atomic_uint g_counter;" NL "void main() {" NL
6130			"  gl_Position = g_transform.mvp * i_position;" NL "  o_color = i_color;" NL
6131			"  const uint index = atomicCounterIncrement(g_counter);" NL
6132			"  imageStore(g_buffer, int(index), gl_Position);" NL "}";
6133		const char* const glsl_fs =
6134			"#version 420 core" NL "layout(location = 3) in vec4 i_color;" NL
6135			"layout(location = 0) out vec4 o_color;" NL "void main() {" NL "  o_color = i_color;" NL "}";
6136		m_vsp = BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6137		m_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_fs);
6138
6139		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6140		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_fsp);
6141
6142		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6143		glBufferData(GL_TEXTURE_BUFFER, sizeof(vec4) * 4, NULL, GL_STATIC_DRAW);
6144
6145		glBindTexture(GL_TEXTURE_BUFFER, m_buffer_tex);
6146		glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, m_buffer);
6147
6148		glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_counter_buffer);
6149		vec4 zero(0);
6150		glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), &zero, GL_STATIC_DRAW);
6151
6152		glBindBuffer(GL_UNIFORM_BUFFER, m_transform_buffer);
6153		mat4 identity(1);
6154		glBufferData(GL_UNIFORM_BUFFER, sizeof(mat4), &identity, GL_STATIC_DRAW);
6155
6156		glClear(GL_COLOR_BUFFER_BIT);
6157		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_counter_buffer);
6158		glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_transform_buffer);
6159		glBindImageTexture(0, m_buffer_tex, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6160		glBindVertexArray(m_vao);
6161		glBindProgramPipeline(m_pipeline);
6162		glDrawArraysInstancedBaseInstance(GL_TRIANGLE_STRIP, 0, 4, 1, 0);
6163
6164		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6165		{
6166			return ERROR;
6167		}
6168
6169		std::vector<vec4> data(4);
6170		glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
6171		glGetBufferSubData(GL_TEXTURE_BUFFER, 0, sizeof(vec4) * 4, &data[0]);
6172
6173		for (int i = 0; i < 4; ++i)
6174		{
6175			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)) &&
6176				!IsEqual(data[i], vec4(-1.0f, 1.0f, 0.0f, 1.0f)) && !IsEqual(data[i], vec4(1.0f, 1.0f, 0.0f, 1.0f)))
6177			{
6178				return ERROR;
6179			}
6180		}
6181
6182		return NO_ERROR;
6183	}
6184
6185	virtual long Cleanup()
6186	{
6187		glDeleteBuffers(1, &m_buffer);
6188		glDeleteBuffers(1, &m_vbo);
6189		glDeleteBuffers(1, &m_counter_buffer);
6190		glDeleteBuffers(1, &m_transform_buffer);
6191		glDeleteTextures(1, &m_buffer_tex);
6192		glDeleteProgram(m_vsp);
6193		glDeleteProgram(m_fsp);
6194		glDeleteVertexArrays(1, &m_vao);
6195		glDeleteProgramPipelines(1, &m_pipeline);
6196		return NO_ERROR;
6197	}
6198};
6199//-----------------------------------------------------------------------------
6200// 2.4.3 AdvancedSSOSubroutine
6201//-----------------------------------------------------------------------------
6202class AdvancedSSOSubroutine : public ShaderImageLoadStoreBase
6203{
6204	GLuint m_texture;
6205	GLuint m_attribless_vao;
6206	GLuint m_program;
6207	GLint  m_draw_buffer;
6208
6209	virtual long Setup()
6210	{
6211		glGenTextures(1, &m_texture);
6212		glGenVertexArrays(1, &m_attribless_vao);
6213
6214		const char* const glsl_vs = "#version 420 core" NL "const int kSize = 3;" NL
6215									"const vec2 g_triangle[kSize] = vec2[3](vec2(-1, -1), vec2(3, -1), vec2(-1, 3));" NL
6216									"void main() {" NL "  gl_Position = vec4(g_triangle[gl_VertexID], 0, 1);" NL "}";
6217		const char* const glsl_fs =
6218			"#version 420 core" NL "writeonly uniform image2DArray g_image0;" NL
6219			"writeonly uniform image2DArray g_image1;" NL "subroutine void Brush(ivec2 coord);" NL
6220			"subroutine uniform Brush g_brush;" NL "subroutine(Brush) void Brush0(ivec2 coord) {" NL
6221			"  imageStore(g_image0, ivec3(coord, 0), vec4(1.0, 0.0, 0.0, 1.0));" NL
6222			"  imageStore(g_image0, ivec3(coord, 1), vec4(0.0, 1.0, 0.0, 1.0));" NL
6223			"  imageStore(g_image0, ivec3(coord, 2), vec4(0.0, 0.0, 1.0, 1.0));" NL "}" NL
6224			"subroutine(Brush) void Brush1(ivec2 coord) {" NL
6225			"  imageStore(g_image1, ivec3(coord, 0), vec4(0.0, 1.0, 0.0, 1.0));" NL
6226			"  imageStore(g_image1, ivec3(coord, 1), vec4(0.0, 0.0, 1.0, 1.0));" NL
6227			"  imageStore(g_image1, ivec3(coord, 2), vec4(1.0, 0.0, 0.0, 1.0));" NL "}" NL "void main() {" NL
6228			"  g_brush(ivec2(gl_FragCoord));" NL "}";
6229		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6230
6231		return NO_ERROR;
6232	}
6233
6234	virtual long Run()
6235	{
6236		int width  = getWindowWidth();
6237		int height = getWindowHeight();
6238		scaleDimensionsToMemory(width, height, 3, 3, 16, 16);
6239
6240		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image0"), 1);
6241		glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image1"), 1);
6242
6243		glBindTexture(GL_TEXTURE_2D_ARRAY, m_texture);
6244		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6245		glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, width, height, 3, 0, GL_RGBA, GL_FLOAT, NULL);
6246
6247		glGetIntegerv(GL_DRAW_BUFFER, &m_draw_buffer);
6248
6249		glDrawBuffer(GL_NONE);
6250		glBindImageTexture(1, m_texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F);
6251		glUseProgram(m_program);
6252		glBindVertexArray(m_attribless_vao);
6253
6254		const GLuint indices[2] = { glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush0"),
6255									glGetSubroutineIndex(m_program, GL_FRAGMENT_SHADER, "Brush1") };
6256
6257		glViewport(0, 0, width, height);
6258		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[0]);
6259		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6260
6261		std::vector<vec4> data(width * height * 3);
6262		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6263		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6264
6265		for (int layer = 0; layer < 3; ++layer)
6266		{
6267			for (int h = 0; h < height; ++h)
6268			{
6269				for (int w = 0; w < width; ++w)
6270				{
6271					const vec4 c = data[layer * width * height + h * width + w];
6272					if (layer == 0 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6273					{
6274						m_context.getTestContext().getLog()
6275							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6276							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6277						return ERROR;
6278					}
6279					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6280					{
6281						m_context.getTestContext().getLog()
6282							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6283							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6284						return ERROR;
6285					}
6286					else if (layer == 2 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6287					{
6288						m_context.getTestContext().getLog()
6289							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6290							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6291						return ERROR;
6292					}
6293				}
6294			}
6295		}
6296
6297		glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &indices[1]);
6298		glDrawArraysInstancedBaseInstance(GL_TRIANGLES, 0, 3, 1, 0);
6299
6300		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6301		glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_FLOAT, &data[0]);
6302
6303		for (int layer = 0; layer < 3; ++layer)
6304		{
6305			for (int h = 0; h < height; ++h)
6306			{
6307				for (int w = 0; w < width; ++w)
6308				{
6309					const vec4 c = data[layer * width * height + h * width + w];
6310					if (layer == 0 && !IsEqual(c, vec4(0.0f, 1.0f, 0.0f, 1.0f)))
6311					{
6312						m_context.getTestContext().getLog()
6313							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6314							<< ") should be (0 1 0 1)" << tcu::TestLog::EndMessage;
6315						return ERROR;
6316					}
6317					else if (layer == 1 && !IsEqual(c, vec4(0.0f, 0.0f, 1.0f, 1.0f)))
6318					{
6319						m_context.getTestContext().getLog()
6320							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6321							<< ") should be (0 0 1 1)" << tcu::TestLog::EndMessage;
6322						return ERROR;
6323					}
6324					else if (layer == 2 && !IsEqual(c, vec4(1.0f, 0.0f, 0.0f, 1.0f)))
6325					{
6326						m_context.getTestContext().getLog()
6327							<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6328							<< ") should be (1 0 0 1)" << tcu::TestLog::EndMessage;
6329						return ERROR;
6330					}
6331				}
6332			}
6333		}
6334		return NO_ERROR;
6335	}
6336
6337	virtual long Cleanup()
6338	{
6339		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6340		glDrawBuffer(m_draw_buffer);
6341		glDeleteTextures(1, &m_texture);
6342		glUseProgram(0);
6343		glDeleteProgram(m_program);
6344		glDeleteVertexArrays(1, &m_attribless_vao);
6345		return NO_ERROR;
6346	}
6347};
6348//-----------------------------------------------------------------------------
6349// 2.4.4 AdvancedSSOPerSample
6350//-----------------------------------------------------------------------------
6351class AdvancedSSOPerSample : public ShaderImageLoadStoreBase
6352{
6353	GLuint m_texture;
6354	GLuint m_pipeline;
6355	GLuint m_vao, m_vbo, m_ebo;
6356	GLuint m_vsp, m_store_fsp, m_load_fsp;
6357
6358	virtual long Setup()
6359	{
6360		m_vao		= 0;
6361		m_vbo		= 0;
6362		m_ebo		= 0;
6363		m_vsp		= 0;
6364		m_store_fsp = 0;
6365		m_load_fsp  = 0;
6366		glGenTextures(1, &m_texture);
6367		glGenProgramPipelines(1, &m_pipeline);
6368
6369		return NO_ERROR;
6370	}
6371
6372	virtual long Run()
6373	{
6374		if (!SupportedSamples(4))
6375			return NOT_SUPPORTED;
6376
6377		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6378
6379		const char* const glsl_vs =
6380			"#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "out gl_PerVertex {" NL
6381			"  vec4 gl_Position;" NL "};" NL "void main() {" NL "  gl_Position = i_position;" NL "}";
6382		const char* const glsl_store_fs =
6383			"#version 420 core" NL "layout(rgba32f) writeonly uniform image2DMS g_image;" NL "void main() {" NL
6384			"  imageStore(g_image, ivec2(gl_FragCoord), gl_SampleID, vec4(gl_SampleID+1));" NL "}";
6385		const char* const glsl_load_fs =
6386			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6387			"layout(rgba32f) readonly uniform image2DMS g_image;" NL "void main() {" NL
6388			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  if (imageLoad(g_image, ivec2(gl_FragCoord), gl_SampleID) != "
6389			"vec4(gl_SampleID+1)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6390		m_vsp		= BuildShaderProgram(GL_VERTEX_SHADER, glsl_vs);
6391		m_store_fsp = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_store_fs);
6392		m_load_fsp  = BuildShaderProgram(GL_FRAGMENT_SHADER, glsl_load_fs);
6393
6394		int width  = getWindowWidth();
6395		int height = getWindowHeight();
6396		scaleDimensionsToMemory(width, height, 1, 1, /* bpp*samples */ 16 * 4, 16);
6397
6398		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texture);
6399		glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA32F, width, height, GL_FALSE);
6400		glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
6401
6402		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_vsp);
6403		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_store_fsp);
6404
6405		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6406
6407		glClear(GL_COLOR_BUFFER_BIT);
6408		glViewport(0, 0, width, height);
6409		glBindVertexArray(m_vao);
6410		glBindProgramPipeline(m_pipeline);
6411		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6412
6413		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6414
6415		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_load_fsp);
6416		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6417
6418		if (!ValidateReadBuffer(0, 0, width, height, vec4(0, 1, 0, 1)))
6419		{
6420			return ERROR;
6421		}
6422		return NO_ERROR;
6423	}
6424
6425	virtual long Cleanup()
6426	{
6427		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6428		glDeleteBuffers(1, &m_vbo);
6429		glDeleteBuffers(1, &m_ebo);
6430		glDeleteTextures(1, &m_texture);
6431		glDeleteProgram(m_vsp);
6432		glDeleteProgram(m_store_fsp);
6433		glDeleteProgram(m_load_fsp);
6434		glDeleteVertexArrays(1, &m_vao);
6435		glDeleteProgramPipelines(1, &m_pipeline);
6436		return NO_ERROR;
6437	}
6438};
6439
6440//-----------------------------------------------------------------------------
6441// 2.5 AdvancedCopyImage
6442//-----------------------------------------------------------------------------
6443class AdvancedCopyImage : public ShaderImageLoadStoreBase
6444{
6445	GLuint m_texture[2];
6446	GLuint m_program;
6447	GLuint m_vao, m_vbo, m_ebo;
6448
6449	virtual long Setup()
6450	{
6451		glGenTextures(2, m_texture);
6452		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6453
6454		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6455									"void main() {" NL "  gl_Position = i_position;" NL "}";
6456		const char* const glsl_fs =
6457			"#version 420 core" NL "layout(rgba32f) readonly uniform image2D g_input_image;" NL
6458			"layout(rgba32f) writeonly uniform image2D g_output_image;" NL "void main() {" NL
6459			"  ivec2 coord = ivec2(gl_FragCoord);" NL
6460			"  imageStore(g_output_image, coord, imageLoad(g_input_image, coord));" NL "  discard;" NL "}";
6461		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6462
6463		return NO_ERROR;
6464	}
6465
6466	virtual long Run()
6467	{
6468		int width  = getWindowWidth();
6469		int height = getWindowHeight();
6470		scaleDimensionsToMemory(width, height, 2, 2, 16, 16);
6471
6472		glUseProgram(m_program);
6473		glUniform1i(glGetUniformLocation(m_program, "g_input_image"), 0);
6474		glUniform1i(glGetUniformLocation(m_program, "g_output_image"), 1);
6475
6476		std::vector<vec4> data(width * height, vec4(7.0f));
6477		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6478		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6479		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &data[0]);
6480
6481		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6482		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6483		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
6484
6485		glBindTexture(GL_TEXTURE_2D, 0);
6486
6487		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
6488		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
6489
6490		glClear(GL_COLOR_BUFFER_BIT);
6491		glViewport(0, 0, width, height);
6492		glBindVertexArray(m_vao);
6493		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6494
6495		std::vector<vec4> rdata(width * height);
6496		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6497		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, &rdata[0]);
6498
6499		for (int h = 0; h < height; ++h)
6500		{
6501			for (int w = 0; w < width; ++w)
6502			{
6503				if (!IsEqual(rdata[h * width + w], vec4(7.0f)))
6504				{
6505					return ERROR;
6506				}
6507			}
6508		}
6509		return NO_ERROR;
6510	}
6511
6512	virtual long Cleanup()
6513	{
6514		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6515		glUseProgram(0);
6516		glDeleteBuffers(1, &m_vbo);
6517		glDeleteBuffers(1, &m_ebo);
6518		glDeleteTextures(2, m_texture);
6519		glDeleteProgram(m_program);
6520		glDeleteVertexArrays(1, &m_vao);
6521		return NO_ERROR;
6522	}
6523};
6524//-----------------------------------------------------------------------------
6525// 2.6 AdvancedAllMips
6526//-----------------------------------------------------------------------------
6527class AdvancedAllMips : public ShaderImageLoadStoreBase
6528{
6529	GLuint m_texture;
6530	GLuint m_store_program, m_load_program;
6531	GLuint m_vao, m_vbo, m_ebo;
6532
6533	virtual long Setup()
6534	{
6535		glGenTextures(1, &m_texture);
6536		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6537
6538		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6539									"void main() {" NL "  gl_Position = i_position;" NL "}";
6540		const char* const glsl_store_fs =
6541			"#version 420 core" NL "layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6542			"  for (int i = 0; i < 6; ++i) {" NL "    imageStore(g_image[i], ivec2(gl_FragCoord), vec4(i));" NL "  }" NL
6543			"  discard;" NL "}";
6544		const char* const glsl_load_fs =
6545			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6546			"layout(rgba32f) uniform image2D g_image[6];" NL "void main() {" NL
6547			"  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  for (int i = 0; i < 6; ++i) {" NL
6548			"    const ivec2 coord = ivec2(gl_FragCoord);" NL "    const vec4 c = imageLoad(g_image[i], coord);" NL
6549			"    if (c != vec4(i) && c != vec4(0.0)) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "  }" NL "}";
6550		m_store_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_store_fs);
6551		m_load_program  = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_load_fs);
6552
6553		return NO_ERROR;
6554	}
6555
6556	virtual long Run()
6557	{
6558		glUseProgram(m_store_program);
6559		glUniform1i(glGetUniformLocation(m_store_program, "g_image[0]"), 0);
6560		glUniform1i(glGetUniformLocation(m_store_program, "g_image[1]"), 1);
6561		glUniform1i(glGetUniformLocation(m_store_program, "g_image[2]"), 2);
6562		glUniform1i(glGetUniformLocation(m_store_program, "g_image[3]"), 3);
6563		glUniform1i(glGetUniformLocation(m_store_program, "g_image[4]"), 4);
6564		glUniform1i(glGetUniformLocation(m_store_program, "g_image[5]"), 5);
6565		glUseProgram(0);
6566
6567		glUseProgram(m_load_program);
6568		glUniform1i(glGetUniformLocation(m_load_program, "g_image[0]"), 0);
6569		glUniform1i(glGetUniformLocation(m_load_program, "g_image[1]"), 1);
6570		glUniform1i(glGetUniformLocation(m_load_program, "g_image[2]"), 2);
6571		glUniform1i(glGetUniformLocation(m_load_program, "g_image[3]"), 3);
6572		glUniform1i(glGetUniformLocation(m_load_program, "g_image[4]"), 4);
6573		glUniform1i(glGetUniformLocation(m_load_program, "g_image[5]"), 5);
6574		glUseProgram(0);
6575
6576		glBindTexture(GL_TEXTURE_2D, m_texture);
6577		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 32, 32, 0, GL_RGBA, GL_FLOAT, NULL);
6578		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16, 0, GL_RGBA, GL_FLOAT, NULL);
6579		glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA32F, 8, 8, 0, GL_RGBA, GL_FLOAT, NULL);
6580		glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA32F, 4, 4, 0, GL_RGBA, GL_FLOAT, NULL);
6581		glTexImage2D(GL_TEXTURE_2D, 4, GL_RGBA32F, 2, 2, 0, GL_RGBA, GL_FLOAT, NULL);
6582		glTexImage2D(GL_TEXTURE_2D, 5, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, NULL);
6583		glBindTexture(GL_TEXTURE_2D, 0);
6584
6585		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6586		glBindImageTexture(1, m_texture, 1, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6587		glBindImageTexture(2, m_texture, 2, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6588		glBindImageTexture(3, m_texture, 3, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6589		glBindImageTexture(4, m_texture, 4, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6590		glBindImageTexture(5, m_texture, 5, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
6591
6592		glViewport(0, 0, 32, 32);
6593		glBindVertexArray(m_vao);
6594
6595		glClear(GL_COLOR_BUFFER_BIT);
6596		glUseProgram(m_store_program);
6597		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6598
6599		glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
6600
6601		glUseProgram(m_load_program);
6602		glDrawElementsInstancedBaseVertex(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6603
6604		if (!ValidateReadBuffer(0, 0, 32, 32, vec4(0, 1, 0, 1)))
6605		{
6606			return ERROR;
6607		}
6608		return NO_ERROR;
6609	}
6610
6611	virtual long Cleanup()
6612	{
6613		glViewport(0, 0, getWindowWidth(), getWindowHeight());
6614		glUseProgram(0);
6615		glDeleteBuffers(1, &m_vbo);
6616		glDeleteBuffers(1, &m_ebo);
6617		glDeleteTextures(1, &m_texture);
6618		glDeleteProgram(m_store_program);
6619		glDeleteProgram(m_load_program);
6620		glDeleteVertexArrays(1, &m_vao);
6621		return NO_ERROR;
6622	}
6623};
6624//-----------------------------------------------------------------------------
6625// 2.7 AdvancedCast
6626//-----------------------------------------------------------------------------
6627class AdvancedCast : public ShaderImageLoadStoreBase
6628{
6629	GLuint m_texture[2];
6630	GLuint m_program;
6631	GLuint m_vao, m_vbo, m_ebo;
6632
6633	virtual long Setup()
6634	{
6635		glGenTextures(2, m_texture);
6636		CreateFullViewportQuad(&m_vao, &m_vbo, &m_ebo);
6637
6638		const char* const glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
6639									"void main() {" NL "  gl_Position = i_position;" NL "}";
6640		const char* const glsl_fs =
6641			"#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
6642			"layout(r32i) coherent uniform iimage2D g_image0;" NL "layout(r32ui) coherent uniform uimage2D g_image1;" NL
6643			"void main() {" NL "  o_color = vec4(0.0, 1.0, 0.0, 1.0);" NL "  ivec2 coord = ivec2(gl_FragCoord);" NL
6644			"  if (imageAtomicAdd(g_image0, coord, 2) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6645			"  if (imageAtomicAdd(g_image0, coord, -1) != 2) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6646			"  if (imageAtomicAdd(g_image1, coord, 1) != 0) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL
6647			"  if (imageAtomicAdd(g_image1, coord, 2) != 1) o_color = vec4(1.0, 0.0, 0.0, 1.0);" NL "}";
6648		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
6649
6650		return NO_ERROR;
6651	}
6652
6653	virtual long Run()
6654	{
6655		glUseProgram(m_program);
6656		glUniform1i(glGetUniformLocation(m_program, "g_image0"), 0);
6657		glUniform1i(glGetUniformLocation(m_program, "g_image1"), 1);
6658
6659		{
6660			std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6661			glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6662			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6663			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6664						 &data[0]);
6665
6666			glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6667			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6668			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
6669						 &data[0]);
6670
6671			glBindTexture(GL_TEXTURE_2D, 0);
6672		}
6673
6674		glBindImageTexture(0, m_texture[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32I);
6675		glBindImageTexture(1, m_texture[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
6676
6677		glClear(GL_COLOR_BUFFER_BIT);
6678		glBindVertexArray(m_vao);
6679		glDrawElementsInstancedBaseInstance(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0, 1, 0);
6680
6681		std::vector<GLubyte> data(getWindowWidth() * getWindowHeight() * 4);
6682		glBindTexture(GL_TEXTURE_2D, m_texture[0]);
6683		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
6684		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6685
6686		for (int h = 0; h < getWindowHeight(); ++h)
6687		{
6688			for (int w = 0; w < getWindowWidth(); ++w)
6689			{
6690				const GLubyte c[4] = {
6691					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6692					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6693				};
6694				if (c[0] != 1 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6695				{
6696					m_context.getTestContext().getLog()
6697						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6698						<< ") should be (1 0 0 0)" << tcu::TestLog::EndMessage;
6699					return ERROR;
6700				}
6701			}
6702		}
6703
6704		glBindTexture(GL_TEXTURE_2D, m_texture[1]);
6705		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
6706
6707		for (int h = 0; h < getWindowHeight(); ++h)
6708		{
6709			for (int w = 0; w < getWindowWidth(); ++w)
6710			{
6711				const GLubyte c[4] = {
6712					data[h * (getWindowWidth() * 4) + w * 4 + 0], data[h * (getWindowWidth() * 4) + w * 4 + 1],
6713					data[h * (getWindowWidth() * 4) + w * 4 + 2], data[h * (getWindowWidth() * 4) + w * 4 + 3],
6714				};
6715				if (c[0] != 3 || c[1] != 0 || c[2] != 0 || c[3] != 0)
6716				{
6717					m_context.getTestContext().getLog()
6718						<< tcu::TestLog::Message << "Color is (" << c[0] << " " << c[1] << c[2] << " " << c[3]
6719						<< ") should be (3 0 0 0)" << tcu::TestLog::EndMessage;
6720					return ERROR;
6721				}
6722			}
6723		}
6724
6725		if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
6726		{
6727			return ERROR;
6728		}
6729		return NO_ERROR;
6730	}
6731
6732	virtual long Cleanup()
6733	{
6734		glUseProgram(0);
6735		glDeleteBuffers(1, &m_vbo);
6736		glDeleteBuffers(1, &m_ebo);
6737		glDeleteTextures(2, m_texture);
6738		glDeleteProgram(m_program);
6739		glDeleteVertexArrays(1, &m_vao);
6740		return NO_ERROR;
6741	}
6742};
6743
6744/** Test "imageLoad() and imageStore() for single-byte data alignment" description follows.
6745 *
6746 *  Steps:
6747 *  - create two textures: "source" and "destination". Fill "source"
6748 *  texture with unique values. Fill "destination" texture with zeros,
6749 *  - prepare a program object that will read texel from "source" image at given
6750 *  coordinates and write its value to "destination" image at same
6751 *  coordinates,
6752 *  - bind "source" and "destination" textures as "source" and "destination"
6753 *  image uniforms,
6754 *  - render "full screen" quad (left bottom corner at -1,-1 and right top
6755 *  corner at 1,1),
6756 *  - verify that texel values in "destination" texture match those in
6757 *  "source" texture (use glGetTexImage).
6758 *
6759 *  Test with 2D R8UI textures with following dimensions:
6760 *  - 16x16,
6761 *  - 16x17,
6762 *  - 17x16,
6763 *  - 17x17,
6764 *  - 16x18,
6765 *  - 18x16,
6766 *  - 18x18,
6767 *  - 19x16,
6768 *  - 16x19,
6769 *  - 19x19.
6770 *
6771 *  Note that default data alignment should cause problems with packing/
6772 *  /unpacking. Therefore GL_PACK_ALIGNMENT and GL_UNPACK_ALIGNMENT parameters
6773 *  of pixel storage mode have to be changed to one byte alignment.
6774 *
6775 *  Program should consist of vertex and fragment shader. Vertex shader should
6776 *  pass vertex position through. Fragment shader should do imageLoad() and
6777 *  imageStore() operations at coordinates gl_FragCoord.
6778 **/
6779class ImageLoadStoreDataAlignmentTest : public ShaderImageLoadStoreBase
6780{
6781private:
6782	/* Structures */
6783	struct TextureDimensions
6784	{
6785		GLuint m_width;
6786		GLuint m_height;
6787
6788		TextureDimensions(GLuint width, GLuint height) : m_width(width), m_height(height)
6789		{
6790		}
6791	};
6792
6793	/* Typedefs */
6794	typedef std::deque<TextureDimensions> TextureDimensionsList;
6795
6796	/* Fields */
6797	GLuint				  m_destination_texture_id;
6798	GLuint				  m_program_id;
6799	TextureDimensionsList m_texture_dimensions;
6800	GLuint				  m_source_texture_id;
6801	GLuint				  m_vertex_array_object_id;
6802	GLuint				  m_vertex_buffer_id;
6803
6804public:
6805	/* Constructor */
6806	ImageLoadStoreDataAlignmentTest()
6807		: m_destination_texture_id(0)
6808		, m_program_id(0)
6809		, m_source_texture_id(0)
6810		, m_vertex_array_object_id(0)
6811		, m_vertex_buffer_id(0)
6812	{
6813		/* Nothing to be done here */
6814	}
6815
6816	/* Methods inherited from SubcaseBase */
6817	virtual long Setup()
6818	{
6819		/* Shaders code */
6820		const char* const vertex_shader_code = "#version 400 core\n"
6821											   "#extension GL_ARB_shader_image_load_store : require\n"
6822											   "\n"
6823											   "precision highp float;\n"
6824											   "\n"
6825											   "in vec4 vs_in_position;\n"
6826											   "\n"
6827											   "void main()\n"
6828											   "{\n"
6829											   "    gl_Position = vs_in_position;\n"
6830											   "}\n";
6831
6832		const char* const fragment_shader_code =
6833			"#version 400 core\n"
6834			"#extension GL_ARB_shader_image_load_store : require\n"
6835			"\n"
6836			"precision highp float;\n"
6837			"\n"
6838			"layout(r8ui) writeonly uniform uimage2D u_destination_image;\n"
6839			"layout(r8ui) readonly  uniform uimage2D u_source_image;\n"
6840			"\n"
6841			"void main()\n"
6842			"{\n"
6843			"    uvec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
6844			"                         imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
6845			"\n"
6846			"    discard;\n"
6847			"}\n";
6848
6849		/* Vertex postions for "full screen" quad, made with triangle strip */
6850		static const GLfloat m_vertex_buffer_data[] = {
6851			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
6852			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
6853			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
6854			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
6855		};
6856
6857		/* Result of BuildProgram operation */
6858		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
6859
6860		/* Add all tested texture dimensions */
6861		m_texture_dimensions.push_back(TextureDimensions(16, 16));
6862		m_texture_dimensions.push_back(TextureDimensions(16, 17));
6863		m_texture_dimensions.push_back(TextureDimensions(17, 16));
6864		m_texture_dimensions.push_back(TextureDimensions(17, 17));
6865		m_texture_dimensions.push_back(TextureDimensions(16, 18));
6866		m_texture_dimensions.push_back(TextureDimensions(18, 16));
6867		m_texture_dimensions.push_back(TextureDimensions(18, 18));
6868		m_texture_dimensions.push_back(TextureDimensions(16, 19));
6869		m_texture_dimensions.push_back(TextureDimensions(19, 16));
6870		m_texture_dimensions.push_back(TextureDimensions(19, 19));
6871
6872		/* Clean previous error */
6873		glGetError();
6874
6875		/* Set single-byte data alignment */
6876		glPixelStorei(GL_PACK_ALIGNMENT, 1);
6877		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
6878		GLU_EXPECT_NO_ERROR(glGetError(), "PixelStorei");
6879
6880		/* Prepare buffer with vertex positions of "full screen" quad" */
6881		glGenBuffers(1, &m_vertex_buffer_id);
6882		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
6883
6884		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
6885		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
6886
6887		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
6888		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
6889
6890		/* Generate vertex array object */
6891		glGenVertexArrays(1, &m_vertex_array_object_id);
6892		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
6893
6894		/* Prepare program object */
6895		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
6896									fragment_shader_code, &is_program_correct);
6897		if (false == is_program_correct)
6898		{
6899			return ERROR;
6900		}
6901
6902		/* Done */
6903		return NO_ERROR;
6904	}
6905
6906	virtual long Cleanup()
6907	{
6908		/* Reset OpenGL state */
6909		glBindBuffer(GL_ARRAY_BUFFER, 0);
6910		glBindTexture(GL_TEXTURE_2D, 0);
6911		glBindVertexArray(0);
6912		glUseProgram(0);
6913
6914		/* Delete program */
6915		if (0 != m_program_id)
6916		{
6917			glDeleteProgram(m_program_id);
6918			m_program_id = 0;
6919		}
6920
6921		/* Delete textures */
6922		if (0 != m_destination_texture_id)
6923		{
6924			glDeleteTextures(1, &m_destination_texture_id);
6925			m_destination_texture_id = 0;
6926		}
6927
6928		if (0 != m_source_texture_id)
6929		{
6930			glDeleteTextures(1, &m_source_texture_id);
6931			m_source_texture_id = 0;
6932		}
6933
6934		/* Delete vertex array object */
6935		if (0 != m_vertex_array_object_id)
6936		{
6937			glDeleteVertexArrays(1, &m_vertex_array_object_id);
6938			m_vertex_array_object_id = 0;
6939		}
6940
6941		/* Delete buffer */
6942		if (0 != m_vertex_buffer_id)
6943		{
6944			glDeleteBuffers(1, &m_vertex_buffer_id);
6945			m_vertex_buffer_id = 0;
6946		}
6947
6948		/* Done */
6949		return NO_ERROR;
6950	}
6951
6952	virtual long Run()
6953	{
6954		bool result = true;
6955
6956		/* For each dimension */
6957		for (TextureDimensionsList::const_iterator it = m_texture_dimensions.begin(); m_texture_dimensions.end() != it;
6958			 ++it)
6959		{
6960			/* Prepare "source" and "destination" textures */
6961			GLU_EXPECT_NO_ERROR(Create2DR8UIDestinationTexture(it->m_width, it->m_height, m_destination_texture_id),
6962								"Create2DR8UIDestinationTexture");
6963			GLU_EXPECT_NO_ERROR(Create2DR8UISourceTexture(it->m_width, it->m_height, m_source_texture_id),
6964								"Create2DR8UISourceTexture");
6965
6966			/* Copy texture data with imageLoad() and imageStore() operations */
6967			Copy2DR8UITexture(m_destination_texture_id, m_source_texture_id);
6968
6969			/* Compare "source" and "destination" textures */
6970			if (false ==
6971				Compare2DR8UITextures(m_destination_texture_id, m_source_texture_id, it->m_width, it->m_height))
6972			{
6973				m_context.getTestContext().getLog()
6974					<< tcu::TestLog::Message
6975					<< "Copy with imageLoad and imageStore failed for textures: " << it->m_width << "x" << it->m_height
6976					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
6977
6978				result = false;
6979			}
6980
6981			/* Destroy "source" and "destination" textures */
6982			glDeleteTextures(1, &m_destination_texture_id);
6983			glDeleteTextures(1, &m_source_texture_id);
6984
6985			m_destination_texture_id = 0;
6986			m_source_texture_id		 = 0;
6987		}
6988
6989		if (false == result)
6990		{
6991			return ERROR;
6992		}
6993
6994		/* Done */
6995		return NO_ERROR;
6996	}
6997
6998private:
6999	/* Private methods */
7000
7001	/** Binds a texture to user-specified image unit and updates relevant sampler uniform
7002	 *
7003	 * @param program_id   Program object id
7004	 * @param texture_id   Texture id
7005	 * @param image_unit   Index of image unit
7006	 * @param uniform_name Name of image uniform
7007	 **/
7008	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, const char* uniform_name)
7009	{
7010		/* Uniform location and invalid value */
7011		static const GLint invalid_uniform_location = -1;
7012		GLint			   image_uniform_location   = 0;
7013
7014		/* Get uniform location */
7015		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7016		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7017		if (invalid_uniform_location == image_uniform_location)
7018		{
7019			throw tcu::InternalError("A required uniform is considered inactive", uniform_name, __FILE__, __LINE__);
7020		}
7021
7022		/* Bind texture to image unit */
7023		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_R8UI);
7024		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7025
7026		/* Set uniform to image unit */
7027		glUniform1i(image_uniform_location, image_unit);
7028		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7029	}
7030
7031	/** Compare two 2D R8UI textures
7032	 *
7033	 * @param left_texture_id  Id of "left" texture object
7034	 * @param right_texture_id Id of "right" texture object
7035	 * @param width            Width of the textures
7036	 * @param height           Height of the textures
7037	 *
7038	 * @return true when texture data is identical, false otherwise
7039	 **/
7040	bool Compare2DR8UITextures(GLuint left_texture_id, GLuint right_texture_id, GLuint width, GLuint height)
7041	{
7042		/* Size of textures */
7043		const GLuint texture_data_size = width * height;
7044
7045		/* Storage for texture data */
7046		std::vector<GLubyte> left_texture_data;
7047		std::vector<GLubyte> right_texture_data;
7048
7049		/* Alocate memory for texture data */
7050		left_texture_data.resize(texture_data_size);
7051		right_texture_data.resize(texture_data_size);
7052
7053		/* Get "left" texture data */
7054		glBindTexture(GL_TEXTURE_2D, left_texture_id);
7055		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7056
7057		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &left_texture_data[0]);
7058		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7059
7060		/* Get "right" texture data */
7061		glBindTexture(GL_TEXTURE_2D, right_texture_id);
7062		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7063
7064		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &right_texture_data[0]);
7065		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7066
7067		/* Compare texels */
7068		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7069	}
7070
7071	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7072	 *
7073	 * @param destination_texture_id Id of "destination" texture object
7074	 * @param source_texture_id      Id of "source" texture object
7075	 **/
7076	void Copy2DR8UITexture(GLuint destination_texture_id, GLuint source_texture_id)
7077	{
7078		/* Uniform names */
7079		static const char* const destination_image_uniform_name = "u_destination_image";
7080		static const char* const source_image_uniform_name		= "u_source_image";
7081
7082		/* Attribute name */
7083		static const char* const position_attribute_name = "vs_in_position";
7084
7085		/* Attribute location and invalid value */
7086		static const GLint invalid_attribute_location  = -1;
7087		GLint			   position_attribute_location = 0;
7088
7089		/* Set current program */
7090		glUseProgram(m_program_id);
7091		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7092
7093		/* Bind vertex array object */
7094		glBindVertexArray(m_vertex_array_object_id);
7095		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7096
7097		/* Bind buffer with quad vertex positions */
7098		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7099		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7100
7101		/* Set up position attribute */
7102		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7103		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7104		if (invalid_attribute_location == position_attribute_location)
7105		{
7106			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7107									 __LINE__);
7108		}
7109
7110		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7111							  0 /* stride */, 0);
7112		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7113
7114		glEnableVertexAttribArray(position_attribute_location);
7115		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7116
7117		/* Set up textures as source and destination images */
7118		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, destination_image_uniform_name);
7119		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, source_image_uniform_name);
7120
7121		/* Execute draw */
7122		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7123		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7124	}
7125
7126	/** Create 2D R8UI texture and fills it with zeros
7127	 *
7128	 * @param width          Width of created texture
7129	 * @param height         Height of created texture
7130	 * @param out_texture_id Id of created texture, not modified if operation fails
7131	 *
7132	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7133	 **/
7134	GLenum Create2DR8UIDestinationTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7135	{
7136		/* Texture size */
7137		const GLuint texture_size = width * height;
7138
7139		/* Prepare storage for texture data */
7140		std::vector<GLubyte> texture_data;
7141		texture_data.resize(texture_size);
7142
7143		/* Set all texels */
7144		for (GLuint i = 0; i < texture_size; ++i)
7145		{
7146			texture_data[i] = 0;
7147		}
7148
7149		/* Create texture */
7150		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7151	}
7152
7153	/** Create 2D R8UI texture and fills it with increasing values, starting from 0
7154	 *
7155	 * @param width          Width of created texture
7156	 * @param height         Height of created texture
7157	 * @param out_texture_id Id of created texture, not modified if operation fails
7158	 *
7159	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7160	 **/
7161	GLenum Create2DR8UISourceTexture(GLuint width, GLuint height, GLuint& out_texture_id)
7162	{
7163		/* Texture size */
7164		const GLuint texture_size = width * height;
7165
7166		/* Value of texel */
7167		GLubyte texel_value = 0;
7168
7169		/* Prepare storage for texture data */
7170		std::vector<GLubyte> texture_data;
7171		texture_data.resize(texture_size);
7172
7173		/* Set all texels */
7174		for (GLuint i = 0; i < texture_size; ++i)
7175		{
7176			texture_data[i] = texel_value++;
7177		}
7178
7179		/* Create texture */
7180		return Create2DR8UITexture(width, height, texture_data, out_texture_id);
7181	}
7182
7183	/** Create 2D R8UI texture and fills it with user-provided data
7184	 *
7185	 * @param width          Width of created texture
7186	 * @param height         Height of created texture
7187	 * @param texture_data   Texture data
7188	 * @param out_texture_id Id of created texture, not modified if operation fails
7189	 *
7190	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7191	 **/
7192	GLenum Create2DR8UITexture(GLuint width, GLuint height, const std::vector<GLubyte>& texture_data,
7193							   GLuint& out_texture_id)
7194	{
7195		GLenum err		  = 0;
7196		GLuint texture_id = 0;
7197
7198		/* Generate texture */
7199		glGenTextures(1, &texture_id);
7200		err = glGetError();
7201		if (GL_NO_ERROR != err)
7202		{
7203			return err;
7204		}
7205
7206		/* Bind texture */
7207		glBindTexture(GL_TEXTURE_2D, texture_id);
7208		err = glGetError();
7209		if (GL_NO_ERROR != err)
7210		{
7211			glDeleteTextures(1, &texture_id);
7212			return err;
7213		}
7214
7215		/* Allocate storage and fill texture */
7216		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R8UI, width, height, 0 /* border */, GL_RED_INTEGER,
7217					 GL_UNSIGNED_BYTE, &texture_data[0]);
7218		err = glGetError();
7219		if (GL_NO_ERROR != err)
7220		{
7221			glDeleteTextures(1, &texture_id);
7222			return err;
7223		}
7224
7225		/* Make texture complete */
7226		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
7227		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
7228		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7229		err = glGetError();
7230		if (GL_NO_ERROR != err)
7231		{
7232			glDeleteTextures(1, &texture_id);
7233			return err;
7234		}
7235
7236		/* Set out_texture_id */
7237		out_texture_id = texture_id;
7238
7239		/* Done */
7240		return GL_NO_ERROR;
7241	}
7242};
7243
7244/** Test "imageLoad() and imageStore() for non-layered image bindings" description follows.
7245 *
7246 *  Steps: same as in test 1 (ImageLoadStoreDataAlignmentTest).
7247 *
7248 *  Test non-layered image bindings (BindImageTexture <layered>: false) with:
7249 *  | Type           | Dimensions |
7250 *  | 2D_ARRAY       | 64x64x6    |
7251 *  | 3D             | 64x64x6    |
7252 *  | CUBE_MAP       | 64         |
7253 *  | CUBE_MAP_ARRAY | 64x3       |
7254 *
7255 *  Use RGBA8 format. All layers shall be tested.
7256 *
7257 *  Program should consist of vertex and fragment shader. Vertex shader should
7258 *  pass vertex position through. Fragment shader should do imageLoad() and
7259 *  imageStore() operations at coordinates gl_FragCoord. Fragment shader should
7260 *  use image2D as image type.
7261 **/
7262class ImageLoadStoreNonLayeredBindingTest : public ShaderImageLoadStoreBase
7263{
7264private:
7265	/* Structures */
7266	struct TextureShapeDefinition
7267	{
7268		GLuint m_edge;
7269		GLuint m_n_elements;
7270		GLenum m_type;
7271
7272		TextureShapeDefinition(GLuint edge, GLuint n_elements, GLenum type)
7273			: m_edge(edge), m_n_elements(n_elements), m_type(type)
7274		{
7275		}
7276	};
7277
7278	/* Typedefs */
7279	typedef std::deque<TextureShapeDefinition> TextureShapeDefinitionList;
7280
7281	/* Fields */
7282	GLuint					   m_destination_texture_id;
7283	GLuint					   m_program_id;
7284	TextureShapeDefinitionList m_texture_shape_definitions;
7285	GLuint					   m_source_texture_id;
7286	GLuint					   m_vertex_array_object_id;
7287	GLuint					   m_vertex_buffer_id;
7288
7289public:
7290	/* Constructor */
7291	ImageLoadStoreNonLayeredBindingTest()
7292		: m_destination_texture_id(0)
7293		, m_program_id(0)
7294		, m_source_texture_id(0)
7295		, m_vertex_array_object_id(0)
7296		, m_vertex_buffer_id(0)
7297	{
7298		/* Nothing to be done here */
7299	}
7300
7301	/* Methods inherited from SubcaseBase */
7302	virtual long Setup()
7303	{
7304		/* Shaders code */
7305		const char* const vertex_shader_code = "#version 400 core\n"
7306											   "#extension GL_ARB_shader_image_load_store : require\n"
7307											   "\n"
7308											   "precision highp float;\n"
7309											   "\n"
7310											   "in vec4 vs_in_position;\n"
7311											   "\n"
7312											   "void main()\n"
7313											   "{\n"
7314											   "    gl_Position = vs_in_position;\n"
7315											   "}\n";
7316
7317		const char* const fragment_shader_code =
7318			"#version 400 core\n"
7319			"#extension GL_ARB_shader_image_load_store : require\n"
7320			"\n"
7321			"precision highp float;\n"
7322			"\n"
7323			"layout(rgba8) writeonly uniform image2D u_destination_image;\n"
7324			"layout(rgba8) readonly  uniform image2D u_source_image;\n"
7325			"\n"
7326			"void main()\n"
7327			"{\n"
7328			"    vec4 loaded_color = imageLoad (u_source_image,      ivec2(gl_FragCoord));\n"
7329			"                        imageStore(u_destination_image, ivec2(gl_FragCoord), loaded_color);\n"
7330			"\n"
7331			"    discard;\n"
7332			"}\n";
7333
7334		/* Vertex postions for "full screen" quad, defined as a triangle strip */
7335		static const GLfloat m_vertex_buffer_data[] = {
7336			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
7337			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
7338			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
7339			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
7340		};
7341
7342		/* Result of BuildProgram operation */
7343		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
7344
7345		/* Add all tested texture shapes */
7346		int texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
7347		m_texture_shape_definitions.push_back(
7348			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_2D_ARRAY));
7349		m_texture_shape_definitions.push_back(
7350			TextureShapeDefinition(texture_edge /* edge */, 6 /* n_elements */, GL_TEXTURE_3D));
7351		m_texture_shape_definitions.push_back(
7352			TextureShapeDefinition(texture_edge /* edge */, 1 /* n_elements */, GL_TEXTURE_CUBE_MAP));
7353		m_texture_shape_definitions.push_back(
7354			TextureShapeDefinition(texture_edge /* edge */, 3 /* n_elements */, GL_TEXTURE_CUBE_MAP_ARRAY));
7355
7356		/* Prepare buffer with vertex positions of "full screen" quad" */
7357		glGenBuffers(1, &m_vertex_buffer_id);
7358		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
7359
7360		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7361		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7362
7363		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
7364		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
7365
7366		/* Generate vertex array object */
7367		glGenVertexArrays(1, &m_vertex_array_object_id);
7368		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
7369
7370		/* Prepare program object */
7371		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /* src_gs */,
7372									fragment_shader_code, &is_program_correct);
7373		if (false == is_program_correct)
7374		{
7375			return ERROR;
7376		}
7377
7378		/* Done */
7379		return NO_ERROR;
7380	}
7381
7382	virtual long Cleanup()
7383	{
7384		/* Reset OpenGL state */
7385		glBindBuffer(GL_ARRAY_BUFFER, 0);
7386		glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
7387		glBindTexture(GL_TEXTURE_3D, 0);
7388		glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
7389		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
7390		glBindVertexArray(0);
7391		glUseProgram(0);
7392
7393		/* Delete program */
7394		if (0 != m_program_id)
7395		{
7396			glDeleteProgram(m_program_id);
7397			m_program_id = 0;
7398		}
7399
7400		/* Delete textures */
7401		if (0 != m_destination_texture_id)
7402		{
7403			glDeleteTextures(1, &m_destination_texture_id);
7404			m_destination_texture_id = 0;
7405		}
7406
7407		if (0 != m_source_texture_id)
7408		{
7409			glDeleteTextures(1, &m_source_texture_id);
7410			m_source_texture_id = 0;
7411		}
7412
7413		/* Delete vertex array object */
7414		if (0 != m_vertex_array_object_id)
7415		{
7416			glDeleteVertexArrays(1, &m_vertex_array_object_id);
7417			m_vertex_array_object_id = 0;
7418		}
7419
7420		/* Delete buffer */
7421		if (0 != m_vertex_buffer_id)
7422		{
7423			glDeleteBuffers(1, &m_vertex_buffer_id);
7424			m_vertex_buffer_id = 0;
7425		}
7426
7427		/* Done */
7428		return NO_ERROR;
7429	}
7430
7431	virtual long Run()
7432	{
7433		bool result = true;
7434
7435		/* For each shape */
7436		for (TextureShapeDefinitionList::const_iterator it = m_texture_shape_definitions.begin();
7437			 m_texture_shape_definitions.end() != it; ++it)
7438		{
7439			const GLuint n_layers = GetTotalNumberOfLayers(it->m_n_elements, it->m_type);
7440
7441			/* Prepare "source" and "destination" textures */
7442			GLU_EXPECT_NO_ERROR(
7443				CreateRGBA8DestinationTexture(it->m_edge, it->m_n_elements, it->m_type, m_destination_texture_id),
7444				"Create2DR8UIDestinationTexture");
7445			GLU_EXPECT_NO_ERROR(CreateRGBA8SourceTexture(it->m_edge, it->m_n_elements, it->m_type, m_source_texture_id),
7446								"Create2DR8UISourceTexture");
7447
7448			/* Copy texture data with imageLoad() and imageStore() operations */
7449			CopyRGBA8Texture(m_destination_texture_id, m_source_texture_id, n_layers);
7450
7451			/* Compare "source" and "destination" textures */
7452			if (false ==
7453				CompareRGBA8Textures(m_destination_texture_id, m_source_texture_id, it->m_edge, n_layers, it->m_type))
7454			{
7455				const char* texture_type = "";
7456				switch (it->m_type)
7457				{
7458				case GL_TEXTURE_2D_ARRAY:
7459					texture_type = "2d array";
7460					break;
7461				case GL_TEXTURE_3D:
7462					texture_type = "3d";
7463					break;
7464				case GL_TEXTURE_CUBE_MAP:
7465					texture_type = "Cube map";
7466					break;
7467				case GL_TEXTURE_CUBE_MAP_ARRAY:
7468					texture_type = "Cube map array";
7469					break;
7470				}
7471
7472				m_context.getTestContext().getLog()
7473					<< tcu::TestLog::Message
7474					<< "Copy  with imageLoad and imageStore failed for texture type: " << texture_type
7475					<< ". Source and destination textures are different" << tcu::TestLog::EndMessage;
7476
7477				result = false;
7478			}
7479
7480			/* Destroy "source" and "destination" textures */
7481			glDeleteTextures(1, &m_destination_texture_id);
7482			glDeleteTextures(1, &m_source_texture_id);
7483
7484			m_destination_texture_id = 0;
7485			m_source_texture_id		 = 0;
7486		}
7487
7488		if (false == result)
7489		{
7490			return ERROR;
7491		}
7492
7493		/* Done */
7494		return NO_ERROR;
7495	}
7496
7497private:
7498	/* Private methods */
7499
7500	/** Binds a texture to user-specified image unit and update relevant sampler uniform
7501	 *
7502	 * @param program_id   Program object id
7503	 * @param texture_id   Texture id
7504	 * @param image_unit   Index of image unit
7505	 * @param layer        Index of layer bound to unit
7506	 * @param uniform_name Name of image uniform
7507	 **/
7508	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLuint image_unit, GLuint layer,
7509							const char* uniform_name)
7510	{
7511		static const GLint invalid_uniform_location = -1;
7512		GLint			   image_uniform_location   = 0;
7513
7514		/* Get uniform location */
7515		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
7516		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
7517		if (invalid_uniform_location == image_uniform_location)
7518		{
7519			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
7520		}
7521
7522		/* Bind texture to image unit */
7523		glBindImageTexture(image_unit, texture_id, 0 /* level */, GL_FALSE /* layered */, layer, GL_READ_WRITE,
7524						   GL_RGBA8);
7525		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
7526
7527		/* Set uniform to image unit */
7528		glUniform1i(image_uniform_location, image_unit);
7529		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
7530	}
7531
7532	/** Compare two 2D R8UI textures
7533	 *
7534	 * @param left_texture_id  Id of "left" texture object
7535	 * @param right_texture_id Id of "right" texture object
7536	 * @param edge             Length of texture edge
7537	 * @param n_layers         Number of layers to compare
7538	 * @param type             Type of texture
7539	 *
7540	 * @return true when texture data is found identical, false otherwise
7541	 **/
7542	bool CompareRGBA8Textures(GLuint left_texture_id, GLuint right_texture_id, GLuint edge, GLuint n_layers,
7543							  GLenum type)
7544	{
7545		static const GLuint n_components	  = 4; /* RGBA */
7546		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7547
7548		/* Storage for texture data */
7549		std::vector<GLubyte> left_texture_data;
7550		std::vector<GLubyte> right_texture_data;
7551
7552		ExtractTextureData(left_texture_id, edge, n_layers, type, left_texture_data);
7553		ExtractTextureData(right_texture_id, edge, n_layers, type, right_texture_data);
7554
7555		/* Compare texels */
7556		return (0 == memcmp(&left_texture_data[0], &right_texture_data[0], texture_data_size));
7557	}
7558
7559	/** Copy contents of "source" texture to "destination" texture with imageLoad() and imageStore() operations
7560	 *
7561	 * @param destination_texture_id Id of "destination" texture object
7562	 * @param source_texture_id      Id of "source" texture object
7563	 * @param n_layers               Number of layers
7564	 **/
7565	void CopyRGBA8Texture(GLuint destination_texture_id, GLuint source_texture_id, GLuint n_layers)
7566	{
7567		for (GLuint layer = 0; layer < n_layers; ++layer)
7568		{
7569			CopyRGBA8TextureLayer(destination_texture_id, source_texture_id, layer);
7570		}
7571	}
7572
7573	/** Copy contents of layer from "source" texture to "destination" texture with imageLoad() and imageStore() operations
7574	 *
7575	 * @param destination_texture_id Id of "destination" texture object
7576	 * @param source_texture_id      Id of "source" texture object
7577	 * @param layer                  Index of layer
7578	 **/
7579	void CopyRGBA8TextureLayer(GLuint destination_texture_id, GLuint source_texture_id, GLuint layer)
7580	{
7581		/* Uniform names */
7582		static const char* const destination_image_uniform_name = "u_destination_image";
7583		static const char* const source_image_uniform_name		= "u_source_image";
7584
7585		/* Attribute name */
7586		static const char* const position_attribute_name = "vs_in_position";
7587
7588		/* Attribute location and invalid value */
7589		static const GLint invalid_attribute_location  = -1;
7590		GLint			   position_attribute_location = 0;
7591
7592		/* Set current program */
7593		glUseProgram(m_program_id);
7594		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
7595
7596		/* Bind vertex array object */
7597		glBindVertexArray(m_vertex_array_object_id);
7598		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
7599
7600		/* Bind buffer with quad vertex positions */
7601		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
7602		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
7603
7604		/* Set up vertex attribute array for position attribute */
7605		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
7606		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
7607		if (invalid_attribute_location == position_attribute_location)
7608		{
7609			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
7610									 __LINE__);
7611		}
7612
7613		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE /* normalized */,
7614							  0 /* stride */, 0 /* pointer */);
7615		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
7616
7617		glEnableVertexAttribArray(position_attribute_location);
7618		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
7619
7620		/* Set up textures as source and destination image samplers */
7621		BindTextureToImage(m_program_id, destination_texture_id, 0 /* image_unit */, layer,
7622						   destination_image_uniform_name);
7623		BindTextureToImage(m_program_id, source_texture_id, 1 /* image_unit */, layer, source_image_uniform_name);
7624
7625		/* Execute draw */
7626		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
7627		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
7628	}
7629
7630	/** Creates RGBA8 texture of given type and fills it with zeros
7631	 *
7632	 * @param edge           Edge of created texture
7633	 * @param n_elements     Number of elements in texture array
7634	 * @param target         Target of created texture
7635	 * @param out_texture_id Id of created texture, not modified if operation fails
7636	 *
7637	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7638	 **/
7639	GLenum CreateRGBA8DestinationTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7640	{
7641		/* Constasts to calculate texture size */
7642		static const GLuint n_components = 4; /* RGBA */
7643		const GLuint		layer_size   = edge * edge * n_components;
7644		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7645		const GLuint		texture_size = layer_size * n_layers;
7646
7647		/* Prepare storage for texture data */
7648		std::vector<GLubyte> texture_data;
7649		texture_data.resize(texture_size);
7650
7651		/* Set all texels */
7652		for (GLuint i = 0; i < texture_size; ++i)
7653		{
7654			texture_data[i] = 0;
7655		}
7656
7657		/* Create texture */
7658		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7659	}
7660
7661	/** Creates RGBA8 texture and fills it with [x, y, layer, 0xaa]
7662	 *
7663	 * @param edge           Edge of created texture
7664	 * @param n_elements     Number of elements in texture array
7665	 * @param target         Target of created texture
7666	 * @param out_texture_id Id of created texture, not modified if operation fails
7667	 *
7668	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7669	 **/
7670	GLenum CreateRGBA8SourceTexture(GLuint edge, GLuint n_elements, GLenum target, GLuint& out_texture_id)
7671	{
7672		/* Constants to calculate texture size */
7673		static const GLuint n_components = 4; /* RGBA */
7674		const GLuint		layer_size   = edge * edge * n_components;
7675		const GLuint		n_layers	 = GetTotalNumberOfLayers(n_elements, target);
7676		const GLuint		texture_size = layer_size * n_layers;
7677
7678		/* Value of texel */
7679		GLubyte texel[4] = { 0, 0, 0, 0xaa };
7680
7681		/* Prepare storage for texture data */
7682		std::vector<GLubyte> texture_data;
7683		texture_data.resize(texture_size);
7684
7685		/* Set all texels */
7686		for (GLuint layer = 0; layer < n_layers; ++layer)
7687		{
7688			const GLuint layer_offset = layer_size * layer;
7689
7690			texel[2] = static_cast<GLubyte>(layer);
7691
7692			for (GLuint y = 0; y < edge; ++y)
7693			{
7694				const GLuint line_offset = y * edge * n_components + layer_offset;
7695
7696				texel[1] = static_cast<GLubyte>(y);
7697
7698				for (GLuint x = 0; x < edge; ++x)
7699				{
7700					const GLuint texel_offset = x * n_components + line_offset;
7701					texel[0]				  = static_cast<GLubyte>(x);
7702
7703					for (GLuint component = 0; component < n_components; ++component)
7704					{
7705						texture_data[texel_offset + component] = texel[component];
7706					}
7707				}
7708			}
7709		}
7710
7711		/* Create texture */
7712		return CreateRGBA8Texture(edge, target, n_layers, texture_data, out_texture_id);
7713	}
7714
7715	/** Creates RGBA8 texture of given type and fills it provided data
7716	 *
7717	 * @param edge           Edge of created texture
7718	 * @param n_elements     Number of elements in texture array
7719	 * @param target         Target of created texture
7720	 * @param texture_data   Texture data
7721	 * @param out_texture_id Id of created texture, not modified if operation fails
7722	 *
7723	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
7724	 **/
7725	GLenum CreateRGBA8Texture(GLuint edge, GLenum target, GLuint n_layers, const std::vector<GLubyte>& texture_data,
7726							  GLuint& out_texture_id)
7727	{
7728		GLenum err		  = 0;
7729		GLuint texture_id = 0;
7730
7731		/* Generate texture */
7732		glGenTextures(1, &texture_id);
7733		err = glGetError();
7734		if (GL_NO_ERROR != err)
7735		{
7736			return err;
7737		}
7738
7739		/* Bind texture */
7740		glBindTexture(target, texture_id);
7741		err = glGetError();
7742		if (GL_NO_ERROR != err)
7743		{
7744			glDeleteTextures(1, &texture_id);
7745			return err;
7746		}
7747
7748		/* Allocate storage and fill texture */
7749		if (GL_TEXTURE_CUBE_MAP != target)
7750		{
7751			glTexImage3D(target, 0 /* level */, GL_RGBA8, edge, edge, n_layers, 0 /* border */, GL_RGBA,
7752						 GL_UNSIGNED_BYTE, &texture_data[0]);
7753		}
7754		else
7755		{
7756			const GLuint n_components = 4;
7757			const GLuint layer_size   = edge * edge * n_components;
7758
7759			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7760						 GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7761			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7762						 GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7763			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7764						 GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7765			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7766						 GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7767			glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7768						 GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7769			glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, GL_RGBA8, edge, edge, 0 /* border */, GL_RGBA,
7770						 GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7771		}
7772		err = glGetError();
7773		if (GL_NO_ERROR != err)
7774		{
7775			glDeleteTextures(1, &texture_id);
7776			return err;
7777		}
7778
7779		/* Make texture complete */
7780		glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
7781		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 0);
7782		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7783		err = glGetError();
7784		if (GL_NO_ERROR != err)
7785		{
7786			glDeleteTextures(1, &texture_id);
7787			return err;
7788		}
7789
7790		/* Set out_texture_id */
7791		out_texture_id = texture_id;
7792
7793		/* Done */
7794		return GL_NO_ERROR;
7795	}
7796
7797	/** Extracts texture data
7798	 *
7799	 * @param texture_id   Id of texture object
7800	 * @param edge         Length of texture edge
7801	 * @param n_layers     Number of layers
7802	 * @param target       Target of texture
7803	 * @param texture_data Extracted texture data
7804	 **/
7805	void ExtractTextureData(GLuint texture_id, GLuint edge, GLuint n_layers, GLenum target,
7806							std::vector<GLubyte>& texture_data)
7807	{
7808		static const GLuint n_components	  = 4; /* RGBA */
7809		const GLuint		texture_data_size = edge * edge * n_layers * n_components;
7810
7811		/* Alocate memory for texture data */
7812		texture_data.resize(texture_data_size);
7813
7814		/* Bind texture */
7815		glBindTexture(target, texture_id);
7816		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
7817
7818		/* Get data */
7819		if (GL_TEXTURE_CUBE_MAP != target)
7820		{
7821			glGetTexImage(target, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
7822		}
7823		else
7824		{
7825			const GLuint layer_size = edge * edge * n_components;
7826
7827			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0 * layer_size]);
7828			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[1 * layer_size]);
7829			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[2 * layer_size]);
7830			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[3 * layer_size]);
7831			glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[4 * layer_size]);
7832			glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[5 * layer_size]);
7833		}
7834
7835		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
7836	}
7837
7838	/** Get number of layers per single element for given type of texture
7839	 *
7840	 * @param target Target of texture
7841	 *
7842	 * @return Number of layers
7843	 **/
7844	GLuint GetLayersPerElement(GLenum target)
7845	{
7846		switch (target)
7847		{
7848		case GL_TEXTURE_2D_ARRAY:
7849		case GL_TEXTURE_3D:
7850			return 1;
7851		case GL_TEXTURE_CUBE_MAP:
7852		case GL_TEXTURE_CUBE_MAP_ARRAY:
7853			return 6;
7854		default:
7855			throw tcu::InternalError("Not supported texture type", "", __FILE__, __LINE__);
7856		}
7857	}
7858
7859	/** Get total number of layers in texture of given type and number of array elements
7860	 *
7861	 * @param n_elements Number of elements in texture array
7862	 * @param target     Target of texture
7863	 *
7864	 * @return Number of layers
7865	 **/
7866	GLuint GetTotalNumberOfLayers(GLuint n_elements, GLenum target)
7867	{
7868		return GetLayersPerElement(target) * n_elements;
7869	}
7870};
7871
7872/** Test "imageLoad() and imageStore() for incomplete textures" description follows.
7873 *
7874 *  Load from incomplete textures should return 0.
7875 *  Store to incomplete textures should be ignored.
7876 *
7877 *  Steps:
7878 *  - create two incomplete textures: "incomplete_source" and
7879 *  "incomplete_destination",
7880 *  - create two complete textures: "complete_source" and
7881 *  "complete_destination",
7882 *  - fill all textures with unique values,
7883 *  - prepare program that will:
7884 *      * load texel from "incomplete_source" and store its value to
7885 *      "complete_destination",
7886 *      * load texel from "complete_source" and store its value to
7887 *      "incomplete_destination".
7888 *  - bind textures to corresponding image uniforms
7889 *  - execute program for all texels,
7890 *  - verify that "incomplete_destination" was not modified and
7891 *  "complete_destination" is filled with zeros.
7892 *
7893 *  Texture is considered incomplete when it has enabled mipmaping (see below)
7894 *  and does not have all mipmap levels defined.  But for the case of Image
7895 *  accessing, it is considered invalid if it is mipmap-incomplete and the
7896 *  level is different to the base level (base-incomplete).
7897 *
7898 *  Creation of incomplete texture:
7899 *  - generate and bind texture object id,
7900 *  - call TexImage2D with <level>: 0,
7901 *  - set GL_TEXTURE_MIN_FILTER? parameter to GL_NEAREST_MIPMAP_LINEAR, (to make
7902 *  sure, it should be initial value),
7903 *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7904 *  - set GL_TEXTURE_MAX_LEVEL parameter, for 64x64 set 7 (log2(min(width,
7905 *  height)).
7906 *
7907 *  Creation of complete texture:
7908 *  - generate and bind texture object id,
7909 *  - call TexImage2D with <level>: 0,
7910 *  - set GL_TEXTURE_BASE_LEVEL parameter to 0.
7911 *  - set GL_TEXTURE_MAX_LEVEL parameter to 0.
7912 *
7913 *  Binding:
7914 *  - Set level == base_level for complete destinations.
7915 *  - Set level != base_level for incomplete destinations that are using
7916 *    mipmap-incomplete textures.
7917 *
7918 *  Test with 2D 64x64 RGBA8 textures.
7919 *
7920 *  Program should consist of vertex and fragment shader. Vertex shader should
7921 *  pass vertex position through. Fragment shader should do imageLoad() and
7922 *  imageStore() operations at coordinates gl_FragCoord.
7923 **/
7924class ImageLoadStoreIncompleteTexturesTest : public ShaderImageLoadStoreBase
7925{
7926private:
7927	/* Constants */
7928	/* Magic numbers that will identify textures, which will be used as their
7929	 * texel value.
7930	 */
7931	static const GLubyte m_complete_destination_magic_number   = 0x11;
7932	static const GLubyte m_complete_source_magic_number		   = 0x22;
7933	static const GLubyte m_incomplete_destination_magic_number = 0x33;
7934	static const GLubyte m_incomplete_source_magic_number	  = 0x44;
7935
7936	/* Texture edge */
7937	GLuint m_texture_edge;
7938
7939	/* Fields */
7940	GLuint m_complete_destination_texture_id;
7941	GLuint m_complete_source_texture_id;
7942	GLuint m_incomplete_destination_texture_id;
7943	GLuint m_incomplete_source_texture_id;
7944	GLuint m_program_id;
7945	GLuint m_vertex_array_object_id;
7946	GLuint m_vertex_buffer_id;
7947
7948public:
7949	/* Constructor */
7950	ImageLoadStoreIncompleteTexturesTest()
7951		: m_texture_edge(0)
7952		, m_complete_destination_texture_id(0)
7953		, m_complete_source_texture_id(0)
7954		, m_incomplete_destination_texture_id(0)
7955		, m_incomplete_source_texture_id(0)
7956		, m_program_id(0)
7957		, m_vertex_array_object_id(0)
7958		, m_vertex_buffer_id(0)
7959	{
7960		/* Nothing to be done here */
7961	}
7962
7963	/* Methods inherited from SubcaseBase */
7964	virtual long Setup()
7965	{
7966		/* Shaders code */
7967		const char* const vertex_shader_code = "#version 400 core\n"
7968											   "#extension GL_ARB_shader_image_load_store : require\n"
7969											   "\n"
7970											   "precision highp float;\n"
7971											   "\n"
7972											   "in vec4 vs_in_position;\n"
7973											   "\n"
7974											   "void main()\n"
7975											   "{\n"
7976											   "    gl_Position = vs_in_position;\n"
7977											   "}\n";
7978
7979		const char* const fragment_shader_code =
7980			"#version 400 core\n"
7981			"#extension GL_ARB_shader_image_load_store : require\n"
7982			"\n"
7983			"precision highp float;\n"
7984			"\n"
7985			"layout(rgba8) writeonly uniform image2D u_complete_destination_image;\n"
7986			"layout(rgba8) readonly  uniform image2D u_complete_source_image;\n"
7987			"layout(rgba8) writeonly uniform image2D u_incomplete_destination_image;\n"
7988			"layout(rgba8) readonly  uniform image2D u_incomplete_source_image;\n"
7989			"\n"
7990			"void main()\n"
7991			"{\n"
7992			"    vec4 complete_loaded_color   = imageLoad (u_complete_source_image,   ivec2(gl_FragCoord));\n"
7993			"    vec4 incomplete_loaded_color = imageLoad (u_incomplete_source_image, ivec2(gl_FragCoord));\n"
7994
7995			"    imageStore(u_complete_destination_image,\n"
7996			"               ivec2(gl_FragCoord),\n"
7997			"               incomplete_loaded_color);\n"
7998			"    imageStore(u_incomplete_destination_image,\n"
7999			"               ivec2(gl_FragCoord),\n"
8000			"               complete_loaded_color);\n"
8001			"\n"
8002			"    discard;\n"
8003			"}\n";
8004
8005		/* Vertex postions for "full screen" quad, made with triangle strip */
8006		static const GLfloat m_vertex_buffer_data[] = {
8007			-1.0f, -1.0f, 0.0f, 1.0f, /* left bottom */
8008			-1.0f, 1.0f,  0.0f, 1.0f, /* left top */
8009			1.0f,  -1.0f, 0.0f, 1.0f, /* right bottom */
8010			1.0f,  1.0f,  0.0f, 1.0f, /* right top */
8011		};
8012
8013		/* Result of BuildProgram operation */
8014		bool is_program_correct = true; /* BuildProgram set false when it fails, but it does not set true on success */
8015
8016		/* Clean previous error */
8017		glGetError();
8018
8019		m_texture_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
8020
8021		/* Prepare textures */
8022		GLU_EXPECT_NO_ERROR(
8023			Create2DRGBA8CompleteTexture(m_complete_destination_magic_number, m_complete_destination_texture_id),
8024			"Create2DRGBA8CompleteTexture");
8025		GLU_EXPECT_NO_ERROR(Create2DRGBA8CompleteTexture(m_complete_source_magic_number, m_complete_source_texture_id),
8026							"Create2DRGBA8CompleteTexture");
8027		GLU_EXPECT_NO_ERROR(
8028			Create2DRGBA8IncompleteTexture(m_incomplete_destination_magic_number, m_incomplete_destination_texture_id),
8029			"Create2DRGBA8IncompleteTexture");
8030		GLU_EXPECT_NO_ERROR(
8031			Create2DRGBA8IncompleteTexture(m_incomplete_source_magic_number, m_incomplete_source_texture_id),
8032			"Create2DRGBA8IncompleteTexture");
8033
8034		/* Prepare buffer with vertex positions of "full screen" quad" */
8035		glGenBuffers(1, &m_vertex_buffer_id);
8036		GLU_EXPECT_NO_ERROR(glGetError(), "GenBuffers");
8037
8038		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8039		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8040
8041		glBufferData(GL_ARRAY_BUFFER, sizeof(m_vertex_buffer_data), m_vertex_buffer_data, GL_STATIC_DRAW);
8042		GLU_EXPECT_NO_ERROR(glGetError(), "BufferData");
8043
8044		/* Generate vertex array object */
8045		glGenVertexArrays(1, &m_vertex_array_object_id);
8046		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8047
8048		/* Prepare program object */
8049		m_program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, 0 /*src_gs */,
8050									fragment_shader_code, &is_program_correct);
8051
8052		if (false == is_program_correct)
8053		{
8054			return ERROR;
8055		}
8056
8057		/* Done */
8058		return NO_ERROR;
8059	}
8060
8061	virtual long Cleanup()
8062	{
8063		/* Reset OpenGL state */
8064		glBindBuffer(GL_ARRAY_BUFFER, 0);
8065		glBindTexture(GL_TEXTURE_2D, 0);
8066		glBindVertexArray(0);
8067		glUseProgram(0);
8068
8069		/* Delete program */
8070		if (0 != m_program_id)
8071		{
8072			glDeleteProgram(m_program_id);
8073			m_program_id = 0;
8074		}
8075
8076		/* Delete textures */
8077		if (0 != m_complete_destination_texture_id)
8078		{
8079			glDeleteTextures(1, &m_complete_destination_texture_id);
8080			m_complete_destination_texture_id = 0;
8081		}
8082
8083		if (0 != m_complete_source_texture_id)
8084		{
8085			glDeleteTextures(1, &m_complete_source_texture_id);
8086			m_complete_source_texture_id = 0;
8087		}
8088
8089		if (0 != m_incomplete_destination_texture_id)
8090		{
8091			glDeleteTextures(1, &m_incomplete_destination_texture_id);
8092			m_incomplete_destination_texture_id = 0;
8093		}
8094
8095		if (0 != m_incomplete_source_texture_id)
8096		{
8097			glDeleteTextures(1, &m_incomplete_source_texture_id);
8098			m_incomplete_source_texture_id = 0;
8099		}
8100
8101		/* Delete vertex array object */
8102		if (0 != m_vertex_array_object_id)
8103		{
8104			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8105			m_vertex_array_object_id = 0;
8106		}
8107
8108		/* Delete buffer */
8109		if (0 != m_vertex_buffer_id)
8110		{
8111			glDeleteBuffers(1, &m_vertex_buffer_id);
8112			m_vertex_buffer_id = 0;
8113		}
8114
8115		/* Done */
8116		return NO_ERROR;
8117	}
8118
8119	virtual long Run()
8120	{
8121		bool result = true;
8122
8123		/* Copy textures data with imageLoad() and imageStore() operations */
8124		Copy2DRGBA8Textures(m_complete_destination_texture_id, m_incomplete_destination_texture_id,
8125							m_complete_source_texture_id, m_incomplete_source_texture_id);
8126
8127		glMemoryBarrier(GL_ALL_BARRIER_BITS);
8128
8129		/* Verify that store to "incomplete destination" was ignored */
8130		if (true ==
8131			CheckIfTextureWasModified(m_incomplete_destination_texture_id, m_incomplete_destination_magic_number))
8132		{
8133			m_context.getTestContext().getLog()
8134				<< tcu::TestLog::Message << "Problem with imageStore, operation modified contents of incomplete texture"
8135				<< tcu::TestLog::EndMessage;
8136
8137			result = false;
8138		}
8139
8140		/* Verify that load from "incomplete source" returned 0 */
8141		if (false == CheckIfTextureIsBlack(m_complete_destination_texture_id))
8142		{
8143			m_context.getTestContext().getLog()
8144				<< tcu::TestLog::Message
8145				<< "Problem with imageLoad, operation returned non 0 result for incomplete texture"
8146				<< tcu::TestLog::EndMessage;
8147
8148			result = false;
8149		}
8150
8151		if (false == result)
8152		{
8153			return ERROR;
8154		}
8155
8156		/* Done */
8157		return NO_ERROR;
8158	}
8159
8160private:
8161	/* Private methods */
8162
8163	/** Bind texture to image unit and sets image uniform to that unit
8164	 *
8165	 * @param program_id   Program object id
8166	 * @param texture_id   Texture id
8167	 * @param level        Texture level
8168	 * @param image_unit   Index of image unit
8169	 * @param uniform_name Name of image uniform
8170	 **/
8171	void BindTextureToImage(GLuint program_id, GLuint texture_id, GLint level, GLuint image_unit, const char* uniform_name)
8172	{
8173		/* Uniform location and invalid value */
8174		static const GLint invalid_uniform_location = -1;
8175		GLint			   image_uniform_location   = 0;
8176
8177		/* Get uniform location */
8178		image_uniform_location = glGetUniformLocation(program_id, uniform_name);
8179		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
8180		if (invalid_uniform_location == image_uniform_location)
8181		{
8182			throw tcu::InternalError("Uniform location is not available", uniform_name, __FILE__, __LINE__);
8183		}
8184
8185		/* Bind texture to image unit */
8186		glBindImageTexture(image_unit, texture_id, level, GL_FALSE, 0 /* layer */, GL_READ_WRITE, GL_RGBA8);
8187		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
8188
8189		/* Set uniform to image unit */
8190		glUniform1i(image_uniform_location, image_unit);
8191		GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
8192	}
8193
8194	/** Check if texture is filled with black color, zeros
8195	 *
8196	 * @param texture_id Id of texture object
8197	 *
8198	 * @return true when texture is fully black, false otherwise
8199	 **/
8200	bool CheckIfTextureIsBlack(GLuint texture_id)
8201	{
8202		/* Constants to calculate size of texture */
8203		static const GLuint n_components	  = 4; /* RGBA */
8204		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8205
8206		/* Storage for texture data */
8207		std::vector<GLubyte> black_texture_data;
8208		std::vector<GLubyte> texture_data;
8209
8210		/* Allocate memory */
8211		black_texture_data.resize(texture_data_size);
8212		texture_data.resize(texture_data_size);
8213
8214		/* Set all texels to black */
8215		for (GLuint i = 0; i < texture_data_size; ++i)
8216		{
8217			black_texture_data[i] = 0;
8218		}
8219
8220		/* Bind texture */
8221		glBindTexture(GL_TEXTURE_2D, texture_id);
8222		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8223
8224		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8225		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8226
8227		/* Compare texels */
8228		return (0 == memcmp(&texture_data[0], &black_texture_data[0], texture_data_size));
8229	}
8230
8231	/** Check if texture was modified
8232	 *
8233	 * @param texture_id   Id of texture object
8234	 * @param nagic_number Magic number that was to create texture
8235	 *
8236	 * @return true if texture contents match expected values, false otherwise
8237	 **/
8238	bool CheckIfTextureWasModified(GLuint texture_id, GLubyte magic_number)
8239	{
8240		/* Constants to calculate size of texture */
8241		static const GLuint n_components	  = 4; /* RGBA */
8242		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8243
8244		/* Storage for texture data */
8245		std::vector<GLubyte> expected_texture_data;
8246		std::vector<GLubyte> texture_data;
8247
8248		/* Allocate memory */
8249		expected_texture_data.resize(texture_data_size);
8250		texture_data.resize(texture_data_size);
8251
8252		/* Prepare expected texels */
8253		for (GLuint y = 0; y < m_texture_edge; ++y)
8254		{
8255			const GLuint line_offset = y * m_texture_edge * n_components;
8256
8257			for (GLuint x = 0; x < m_texture_edge; ++x)
8258			{
8259				const GLuint texel_offset = x * n_components + line_offset;
8260
8261				SetTexel(&expected_texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y),
8262						 magic_number);
8263			}
8264		}
8265
8266		/* Bind texture */
8267		glBindTexture(GL_TEXTURE_2D, texture_id);
8268		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
8269
8270		glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
8271		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
8272
8273		/* Compare texels, true when textures are different */
8274		return (0 != memcmp(&texture_data[0], &expected_texture_data[0], texture_data_size));
8275	}
8276
8277	/** Copy contents of "source" textures to "destination" textures with imageLoad() and imageStore() operations
8278	 *
8279	 * @param complete_destination_texture_id   Id of "complete destination" texture object
8280	 * @param incomplete_destination_texture_id Id of "incomplete destination" texture object
8281	 * @param complete_source_texture_id        Id of "complete source" texture object
8282	 * @param incomplete_source_texture_id      Id of "incomplete source" texture object
8283	 **/
8284	void Copy2DRGBA8Textures(GLuint complete_destination_texture_id, GLuint incomplete_destination_texture_id,
8285							 GLuint complete_source_texture_id, GLuint incomplete_source_texture_id)
8286	{
8287		/* Uniform names */
8288		static const char* const complete_destination_image_uniform_name   = "u_complete_destination_image";
8289		static const char* const complete_source_image_uniform_name		   = "u_complete_source_image";
8290		static const char* const incomplete_destination_image_uniform_name = "u_incomplete_destination_image";
8291		static const char* const incomplete_source_image_uniform_name	  = "u_incomplete_source_image";
8292
8293		/* Attribute name */
8294		static const char* const position_attribute_name = "vs_in_position";
8295
8296		/* Attribute location and invalid value */
8297		static const GLint invalid_attribute_location  = -1;
8298		GLint			   position_attribute_location = 0;
8299
8300		/* Set current program */
8301		glUseProgram(m_program_id);
8302		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
8303
8304		/* Bind vertex array object */
8305		glBindVertexArray(m_vertex_array_object_id);
8306		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8307
8308		/* Bind buffer with quad vertex positions */
8309		glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer_id);
8310		GLU_EXPECT_NO_ERROR(glGetError(), "BindBuffer");
8311
8312		/* Setup position attribute */
8313		position_attribute_location = glGetAttribLocation(m_program_id, position_attribute_name);
8314		GLU_EXPECT_NO_ERROR(glGetError(), "GetAttribLocation");
8315		if (invalid_attribute_location == position_attribute_location)
8316		{
8317			throw tcu::InternalError("Attribute location is not available", position_attribute_name, __FILE__,
8318									 __LINE__);
8319		}
8320
8321		glVertexAttribPointer(position_attribute_location, 4 /*size */, GL_FLOAT, GL_FALSE, 0 /* stride */, 0);
8322		GLU_EXPECT_NO_ERROR(glGetError(), "VertexAttribPointer");
8323
8324		glEnableVertexAttribArray(position_attribute_location);
8325		GLU_EXPECT_NO_ERROR(glGetError(), "EnableVertexAttribArray");
8326
8327		/* Setup textures as source and destination images */
8328		BindTextureToImage(m_program_id, complete_destination_texture_id,
8329						   0 /* texture level */, 0 /* image_unit */,
8330						   complete_destination_image_uniform_name);
8331		BindTextureToImage(m_program_id, complete_source_texture_id,
8332						   0 /* texture level */, 1 /* image_unit */,
8333						   complete_source_image_uniform_name);
8334		BindTextureToImage(m_program_id, incomplete_destination_texture_id,
8335						   2 /* texture level */, 2 /* image_unit */,
8336						   incomplete_destination_image_uniform_name);
8337		BindTextureToImage(m_program_id, incomplete_source_texture_id,
8338						   2 /* texture level */, 3 /* image_unit */,
8339						   incomplete_source_image_uniform_name);
8340
8341		/* Execute draw */
8342		glDrawArrays(GL_TRIANGLE_STRIP, 0 /* first vertex */, 4 /* number of vertices */);
8343		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
8344	}
8345
8346	/** Create complete 2D RGBA8 texture.
8347	 *
8348	 * @param magic_number   Magic number of texture
8349	 * @param out_texture_id Id of created texture, not modified if operation fails
8350	 *
8351	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8352	 **/
8353	GLenum Create2DRGBA8CompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8354	{
8355		/* Constants to calculate size of texture */
8356		static const GLuint n_components	  = 4; /* RGBA */
8357		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8358
8359		/* Error code */
8360		GLenum err = 0;
8361
8362		/* Texture id */
8363		GLuint texture_id = 0;
8364
8365		/* Prepare storage for texture data */
8366		std::vector<GLubyte> texture_data;
8367		texture_data.resize(texture_data_size);
8368
8369		/* Prepare texture data */
8370		for (GLuint y = 0; y < m_texture_edge; ++y)
8371		{
8372			const GLuint line_offset = y * m_texture_edge * n_components;
8373
8374			for (GLuint x = 0; x < m_texture_edge; ++x)
8375			{
8376				const GLuint texel_offset = x * n_components + line_offset;
8377
8378				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8379			}
8380		}
8381
8382		/* Generate texture */
8383		glGenTextures(1, &texture_id);
8384		err = glGetError();
8385		if (GL_NO_ERROR != err)
8386		{
8387			return err;
8388		}
8389
8390		/* Bind texture */
8391		glBindTexture(GL_TEXTURE_2D, texture_id);
8392		err = glGetError();
8393		if (GL_NO_ERROR != err)
8394		{
8395			glDeleteTextures(1, &texture_id);
8396			return err;
8397		}
8398
8399		/* Allocate storage and fill texture */
8400		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8401					 GL_UNSIGNED_BYTE, &texture_data[0]);
8402		err = glGetError();
8403		if (GL_NO_ERROR != err)
8404		{
8405			glDeleteTextures(1, &texture_id);
8406			return err;
8407		}
8408
8409		/* Make texture complete */
8410		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8411		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
8412		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
8413		err = glGetError();
8414		if (GL_NO_ERROR != err)
8415		{
8416			glDeleteTextures(1, &texture_id);
8417			return err;
8418		}
8419
8420		/* Set out_texture_id */
8421		out_texture_id = texture_id;
8422
8423		/* Done */
8424		return GL_NO_ERROR;
8425	}
8426
8427	/** Create incomplete 2D RGBA8 texture
8428	 *
8429	 * @param magic_number   Magic number of texture
8430	 * @param out_texture_id Id of created texture, not modified if operation fails
8431	 *
8432	 * @return GL_NO_ERROR if operation was successful, GL error code otherwise
8433	 **/
8434	GLenum Create2DRGBA8IncompleteTexture(GLubyte magic_number, GLuint& out_texture_id)
8435	{
8436		/* Constants to calculate size of texture */
8437		static const GLuint n_components	  = 4; /* RGBA */
8438		const GLuint		texture_data_size = m_texture_edge * m_texture_edge * n_components;
8439
8440		/* Error code */
8441		GLenum err = 0;
8442
8443		/* Texture id */
8444		GLuint texture_id = 0;
8445
8446		/* Prepare storage for texture data */
8447		std::vector<GLubyte> texture_data;
8448		texture_data.resize(texture_data_size);
8449
8450		/* Prepare texture data */
8451		for (GLuint y = 0; y < m_texture_edge; ++y)
8452		{
8453			const GLuint line_offset = y * m_texture_edge * n_components;
8454
8455			for (GLuint x = 0; x < m_texture_edge; ++x)
8456			{
8457				const GLuint texel_offset = x * n_components + line_offset;
8458
8459				SetTexel(&texture_data[texel_offset], static_cast<GLubyte>(x), static_cast<GLubyte>(y), magic_number);
8460			}
8461		}
8462
8463		/* Generate texture */
8464		glGenTextures(1, &texture_id);
8465		err = glGetError();
8466		if (GL_NO_ERROR != err)
8467		{
8468			return err;
8469		}
8470
8471		/* Bind texture */
8472		glBindTexture(GL_TEXTURE_2D, texture_id);
8473		err = glGetError();
8474		if (GL_NO_ERROR != err)
8475		{
8476			glDeleteTextures(1, &texture_id);
8477			return err;
8478		}
8479
8480		/* Allocate storage and fill texture */
8481		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_texture_edge, m_texture_edge, 0 /* border */, GL_RGBA,
8482					 GL_UNSIGNED_BYTE, &texture_data[0]);
8483		err = glGetError();
8484		if (GL_NO_ERROR != err)
8485		{
8486			glDeleteTextures(1, &texture_id);
8487			return err;
8488		}
8489
8490		/* Make texture incomplete */
8491		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
8492		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 7);
8493		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
8494		err = glGetError();
8495		if (GL_NO_ERROR != err)
8496		{
8497			glDeleteTextures(1, &texture_id);
8498			return err;
8499		}
8500
8501		/* Set out_texture_id */
8502		out_texture_id = texture_id;
8503
8504		/* Done */
8505		return GL_NO_ERROR;
8506	}
8507
8508	/** Prepare "unique" texels.
8509	 *  Texel is assigned with such values: [x_coordinate, y_coordinate, magic_number, 0xcc].
8510	 *
8511	 * @param texel        Storage of texel
8512	 * @param x_coordinate X coordiante of texel
8513	 * @param y_coordinate Y coordinate of texel
8514	 * @param magic_number Magic number of texture
8515	 **/
8516	void SetTexel(GLubyte texel[4], GLubyte x_coordinate, GLubyte y_coordinate, GLubyte magic_number)
8517	{
8518		texel[0] = x_coordinate;
8519		texel[1] = y_coordinate;
8520		texel[2] = magic_number;
8521		texel[3] = 0xcc;
8522	}
8523};
8524
8525/** Test "Refer to the same image unit using multiple uniforms", description follows.
8526 *
8527 * Steps:
8528 * - prepare program object, see details below,
8529 * - prepare 2D R32I texture, width should be equal to the number of image
8530 * uniforms used by program object, height should be 2, fill first row with
8531 * unique values, fill second row with zeros,
8532 * - bind texture to first image unit,
8533 * - set all image uniforms to first image unit,
8534 * - execute program for a single vertex,
8535 * - verify that:
8536 *     - values in first row were negated,
8537 *     - values from first row were copied to second row,
8538 *
8539 * Repeat steps to test all shader stages that support at least 2 image
8540 * uniforms.
8541 *
8542 * Program has to contain all necessary shader stages. Use boilerplate shaders
8543 * for shader stages that are not important for the test.
8544 *
8545 * Tested shader stage should:
8546 * - Use as many different image formats as possible, image formats compatible
8547 * with R32I:
8548 *     * rg16f
8549 *     * r11f_g11f_b10f
8550 *     * r32f
8551 *     * rgb10_a2ui
8552 *     * rgba8ui
8553 *     * rg16ui
8554 *     * r32ui
8555 *     * rgba8i
8556 *     * rg16i
8557 *     * r32i
8558 *     * rgb10_a2
8559 *     * rgba8
8560 *     * rg16
8561 *     * rgba8_snorm
8562 *     * rg16_snorm.
8563 * - Declare maximum allowed number of image uniforms,
8564 *
8565 *     layout(format) uniform gimage2D u_image;
8566 *
8567 * where <format> is selected image format, <gimage2D> is type of 2D image
8568 * compatible with <format> and <u_image> is unique name of uniform.
8569 * Note that image uniforms cannot be declared as array, due to different image
8570 * formats. Therefore separate uniforms have to be used.
8571 * - Include following code snippet:
8572 * for (int i = 0; i < gl_Max*ImageUniforms; ++i)
8573 * {
8574 *     vec row_1_coord(i,0);
8575 *     vec row_2_coord(i,1);
8576 *
8577 *     row_1_value = imageLoad(u_image[i], row_1_coord);
8578 *     imageStore(u_image[i], row_1_coord, -row_1_value);
8579 *     imageStore(u_image[i], row_2_coord, row_1_value);
8580 * }
8581 * where gl_Max*ImageUniforms is the constant corresponding to tested shader
8582 * stage.
8583 **/
8584class ImageLoadStoreMultipleUniformsTest : public ShaderImageLoadStoreBase
8585{
8586private:
8587	/* Types */
8588	/** Details of image format
8589	 *
8590	 **/
8591	struct imageFormatDetails
8592	{
8593		typedef bool (*verificationRoutine)(GLint, GLint, GLint);
8594
8595		const char*			m_image_format;
8596		const char*			m_image_type;
8597		const char*			m_color_type;
8598		GLenum				m_image_unit_format;
8599		verificationRoutine m_verification_routine;
8600	};
8601
8602	template <typename T, GLuint SIZE, GLuint OFFSET, bool = (OFFSET < sizeof(T) * CHAR_BIT)>
8603	struct Masks
8604	{
8605		/** Get mask of bits used to store in bit-field
8606		 *
8607		 * @return Mask
8608		 **/
8609		static inline T RawMask()
8610		{
8611			static const T mask = ValueMask() << OFFSET;
8612
8613			return mask;
8614		}
8615
8616		/** Get mask of bits used to store value.
8617		 *
8618		 * @return Mask
8619		 **/
8620		static inline T ValueMask()
8621		{
8622			static const T mask = (1 << SIZE) - 1;
8623
8624			return mask;
8625		}
8626
8627		/** Get offset.
8628		 *
8629		 * @return offset
8630		 **/
8631		static inline T Offset()
8632		{
8633			return OFFSET;
8634		}
8635	};
8636
8637	template <typename T, GLuint SIZE, GLuint OFFSET>
8638	struct Masks<T, SIZE, OFFSET, false>
8639	{
8640		/** Get mask of bits used to store in bit-field
8641		 *
8642		 * @return Mask
8643		 **/
8644		static inline T RawMask()
8645		{
8646			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8647			return 0;
8648		}
8649
8650		/** Get mask of bits used to store value.
8651		 *
8652		 * @return Mask
8653		 **/
8654		static inline T ValueMask()
8655		{
8656			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8657			return 0;
8658		}
8659
8660		/** Get offset.
8661		 *
8662		 * @return offset
8663		 **/
8664		static inline T Offset()
8665		{
8666			DE_ASSERT(DE_FALSE && "Shouldn't be called");
8667			return 0;
8668		}
8669	};
8670
8671	/** Template class for accessing integer values stored in bit-fields
8672	 *
8673	 **/
8674	template <typename T, GLuint SIZE, GLuint OFFSET>
8675	class Integer
8676	{
8677	public:
8678		/** Constructor
8679		 *
8680		 **/
8681		Integer(T raw) : m_raw(raw)
8682		{
8683		}
8684
8685		/** Extract value from bit-field
8686		 *
8687		 * @return Value
8688		 **/
8689		T Get() const
8690		{
8691			const T mask = Masks<T, SIZE, OFFSET>::RawMask();
8692
8693			const T bits   = m_raw & mask;
8694			const T result = (unsigned)bits >> Masks<T, SIZE, OFFSET>::Offset();
8695
8696			return result;
8697		}
8698
8699		/** Extract value from bit-field and negate it
8700		 *
8701		 * @return Negated value
8702		 **/
8703		T GetNegated() const
8704		{
8705			const T mask  = Masks<T, SIZE, OFFSET>::ValueMask();
8706			const T value = Get();
8707
8708			return Clamp((~value) + 1) & mask;
8709		}
8710
8711		T Clamp(T n) const
8712		{
8713			const bool isUnsigned = (T(0) < T(-1));
8714			const T	min		  = T(isUnsigned ? 0.L : -pow(2.L, int(SIZE - 1)));
8715			const T	max		  = T(isUnsigned ? pow(2.L, int(SIZE)) - 1.L : pow(2.L, int(SIZE - 1)) - 1.L);
8716			const T	x		  = n > max ? max : n;
8717			return x < min ? min : x;
8718		}
8719
8720	private:
8721		T m_raw;
8722	};
8723
8724	/* Enums */
8725	/** Shader stage identification
8726	 *
8727	 **/
8728	enum shaderStage
8729	{
8730		fragmentShaderStage				 = 2,
8731		geometryShaderStage				 = 4,
8732		tesselationControlShaderStage	= 8,
8733		tesselationEvalutaionShaderStage = 16,
8734		vertexShaderStage				 = 32,
8735	};
8736
8737	/** Test result
8738	 *
8739	 **/
8740	enum testResult
8741	{
8742		testFailed		 = -1,
8743		testNotSupported = 1,
8744		testPassed		 = 0
8745	};
8746
8747	/* Constants */
8748	static const GLint m_min_required_image_uniforms = 2;
8749
8750	/* Fields */
8751	GLuint m_program_to_test_fs_stage_id;
8752	GLuint m_program_to_test_gs_stage_id;
8753	GLuint m_program_to_test_tcs_stage_id;
8754	GLuint m_program_to_test_tes_stage_id;
8755	GLuint m_program_to_test_vs_stage_id;
8756	GLuint m_texture_to_test_fs_stage_id;
8757	GLuint m_texture_to_test_gs_stage_id;
8758	GLuint m_texture_to_test_tcs_stage_id;
8759	GLuint m_texture_to_test_tes_stage_id;
8760	GLuint m_texture_to_test_vs_stage_id;
8761	GLuint m_vertex_array_object_id;
8762
8763public:
8764	/* Constructor */
8765	ImageLoadStoreMultipleUniformsTest()
8766		: m_program_to_test_fs_stage_id(0)
8767		, m_program_to_test_gs_stage_id(0)
8768		, m_program_to_test_tcs_stage_id(0)
8769		, m_program_to_test_tes_stage_id(0)
8770		, m_program_to_test_vs_stage_id(0)
8771		, m_texture_to_test_fs_stage_id(0)
8772		, m_texture_to_test_gs_stage_id(0)
8773		, m_texture_to_test_tcs_stage_id(0)
8774		, m_texture_to_test_tes_stage_id(0)
8775		, m_texture_to_test_vs_stage_id(0)
8776		, m_vertex_array_object_id(0)
8777	{
8778		/* Nothing to be done here */
8779	}
8780
8781	/* Methods inherited from SubcaseBase */
8782	virtual long Setup()
8783	{
8784		/* Prepare programs */
8785		m_program_to_test_fs_stage_id  = buildProgramToTestShaderStage(fragmentShaderStage);
8786		m_program_to_test_gs_stage_id  = buildProgramToTestShaderStage(geometryShaderStage);
8787		m_program_to_test_tcs_stage_id = buildProgramToTestShaderStage(tesselationControlShaderStage);
8788		m_program_to_test_tes_stage_id = buildProgramToTestShaderStage(tesselationEvalutaionShaderStage);
8789		m_program_to_test_vs_stage_id  = buildProgramToTestShaderStage(vertexShaderStage);
8790
8791		/* Prepare textures */
8792		m_texture_to_test_fs_stage_id  = createTextureToTestShaderStage(fragmentShaderStage);
8793		m_texture_to_test_gs_stage_id  = createTextureToTestShaderStage(geometryShaderStage);
8794		m_texture_to_test_tcs_stage_id = createTextureToTestShaderStage(tesselationControlShaderStage);
8795		m_texture_to_test_tes_stage_id = createTextureToTestShaderStage(tesselationEvalutaionShaderStage);
8796		m_texture_to_test_vs_stage_id  = createTextureToTestShaderStage(vertexShaderStage);
8797
8798		/* Generate vertex array object */
8799		glGenVertexArrays(1, &m_vertex_array_object_id);
8800		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
8801
8802		/* Bind vertex array object */
8803		glBindVertexArray(m_vertex_array_object_id);
8804		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
8805
8806		/* Set vertices number for patches */
8807		glPatchParameteri(GL_PATCH_VERTICES, 1);
8808
8809		/* Done */
8810		return NO_ERROR;
8811	}
8812
8813	virtual long Cleanup()
8814	{
8815		glUseProgram(0);
8816
8817		/* Delete programs */
8818		if (0 != m_program_to_test_fs_stage_id)
8819		{
8820			glDeleteProgram(m_program_to_test_fs_stage_id);
8821			m_program_to_test_fs_stage_id = 0;
8822		}
8823
8824		if (0 != m_program_to_test_gs_stage_id)
8825		{
8826			glDeleteProgram(m_program_to_test_gs_stage_id);
8827			m_program_to_test_gs_stage_id = 0;
8828		}
8829
8830		if (0 != m_program_to_test_tcs_stage_id)
8831		{
8832			glDeleteProgram(m_program_to_test_tcs_stage_id);
8833			m_program_to_test_tcs_stage_id = 0;
8834		}
8835
8836		if (0 != m_program_to_test_tes_stage_id)
8837		{
8838			glDeleteProgram(m_program_to_test_tes_stage_id);
8839			m_program_to_test_tes_stage_id = 0;
8840		}
8841
8842		if (0 != m_program_to_test_vs_stage_id)
8843		{
8844			glDeleteProgram(m_program_to_test_vs_stage_id);
8845			m_program_to_test_vs_stage_id = 0;
8846		}
8847
8848		/* Delete textures */
8849		if (0 != m_texture_to_test_fs_stage_id)
8850		{
8851			glDeleteTextures(1, &m_texture_to_test_fs_stage_id);
8852			m_texture_to_test_fs_stage_id = 0;
8853		}
8854
8855		if (0 != m_texture_to_test_gs_stage_id)
8856		{
8857			glDeleteTextures(1, &m_texture_to_test_gs_stage_id);
8858			m_texture_to_test_gs_stage_id = 0;
8859		}
8860
8861		if (0 != m_texture_to_test_tcs_stage_id)
8862		{
8863			glDeleteTextures(1, &m_texture_to_test_tcs_stage_id);
8864			m_texture_to_test_tcs_stage_id = 0;
8865		}
8866
8867		if (0 != m_texture_to_test_tes_stage_id)
8868		{
8869			glDeleteTextures(1, &m_texture_to_test_tes_stage_id);
8870			m_texture_to_test_tes_stage_id = 0;
8871		}
8872
8873		if (0 != m_texture_to_test_vs_stage_id)
8874		{
8875			glDeleteTextures(1, &m_texture_to_test_vs_stage_id);
8876			m_texture_to_test_vs_stage_id = 0;
8877		}
8878
8879		/* Delete vertex array object id */
8880		if (0 != m_vertex_array_object_id)
8881		{
8882			glDeleteVertexArrays(1, &m_vertex_array_object_id);
8883			m_vertex_array_object_id = 0;
8884		}
8885
8886		/* Done */
8887		return NO_ERROR;
8888	}
8889
8890	virtual long Run()
8891	{
8892		bool result = true;
8893
8894		if (testFailed == testShaderStage(fragmentShaderStage))
8895		{
8896			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with fragment shader stage!"
8897												<< tcu::TestLog::EndMessage;
8898
8899			result = false;
8900		}
8901
8902		if (testFailed == testShaderStage(geometryShaderStage))
8903		{
8904			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with geometry shader stage!"
8905												<< tcu::TestLog::EndMessage;
8906
8907			result = false;
8908		}
8909
8910		if (testFailed == testShaderStage(tesselationControlShaderStage))
8911		{
8912			m_context.getTestContext().getLog() << tcu::TestLog::Message
8913												<< "Problems with tesselation control shader stage!"
8914												<< tcu::TestLog::EndMessage;
8915
8916			result = false;
8917		}
8918
8919		if (testFailed == testShaderStage(tesselationEvalutaionShaderStage))
8920		{
8921			m_context.getTestContext().getLog() << tcu::TestLog::Message
8922												<< "Problems with tesselation evaluation shader stage!"
8923												<< tcu::TestLog::EndMessage;
8924
8925			result = false;
8926		}
8927
8928		if (testFailed == testShaderStage(vertexShaderStage))
8929		{
8930			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Problems with vertex shader stage!"
8931												<< tcu::TestLog::EndMessage;
8932
8933			result = false;
8934		}
8935
8936		if (false == result)
8937		{
8938			return ERROR;
8939		}
8940
8941		/* Done */
8942		return NO_ERROR;
8943	}
8944
8945private:
8946	/* Static routines */
8947	/** Provide image format details for given index
8948	 *
8949	 * @param index       Index
8950	 * @param out_details Image format detail instance
8951	 **/
8952	static void getImageUniformDeclarationDetails(GLuint index, imageFormatDetails& out_details)
8953	{
8954		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails default_format_details = {
8955			"r32i", "iimage2D", "ivec4", GL_R32I, ImageLoadStoreMultipleUniformsTest::verifyInteger
8956		};
8957
8958		static const ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details[] = {
8959			{ "rg16f", "image2D", "vec4", GL_RG16F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLushort> },
8960			{ "r11f_g11f_b10f", "image2D", "vec4", GL_R11F_G11F_B10F,
8961			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8962			{ "r32f", "image2D", "vec4", GL_R32F, ImageLoadStoreMultipleUniformsTest::verifyFloat<GLuint> },
8963			{ "rgb10_a2", "image2D", "vec4", GL_RGB10_A2,
8964			  ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8965			{ "rgba8", "image2D", "vec4", GL_RGBA8, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8966			{ "rg16", "image2D", "vec4", GL_RG16, ImageLoadStoreMultipleUniformsTest::verifyFloatUnsigned<GLuint> },
8967			{ "rgba8_snorm", "image2D", "vec4", GL_RGBA8_SNORM,
8968			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLbyte> },
8969			{ "rg16_snorm", "image2D", "vec4", GL_RG16_SNORM,
8970			  ImageLoadStoreMultipleUniformsTest::verifyFloatSignedNorm<GLshort> },
8971			{ "rgb10_a2ui", "uimage2D", "uvec4", GL_RGB10_A2UI,
8972			  ImageLoadStoreMultipleUniformsTest::verifyInteger<10, 10, 10, 2, GLuint> },
8973			{ "rgba8ui", "uimage2D", "uvec4", GL_RGBA8UI,
8974			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLuint> },
8975			{ "rg16ui", "uimage2D", "uvec4", GL_RG16UI,
8976			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLuint> },
8977			{ "r32ui", "uimage2D", "uvec4", GL_R32UI, ImageLoadStoreMultipleUniformsTest::verifyInteger },
8978			{ "rgba8i", "iimage2D", "ivec4", GL_RGBA8I,
8979			  ImageLoadStoreMultipleUniformsTest::verifyInteger<8, 8, 8, 8, GLint> },
8980			{ "rg16i", "iimage2D", "ivec4", GL_RG16I,
8981			  ImageLoadStoreMultipleUniformsTest::verifyInteger<16, 16, 0, 0, GLint> }
8982		};
8983
8984		static const GLuint n_imageUniformFormatDetails =
8985			sizeof(format_details) / sizeof(ImageLoadStoreMultipleUniformsTest::imageFormatDetails);
8986
8987		if (n_imageUniformFormatDetails <= index)
8988		{
8989			out_details = default_format_details;
8990		}
8991		else
8992		{
8993			out_details = format_details[index];
8994		}
8995	}
8996
8997	/** Write name of image uniform at given index to output stream
8998	 *
8999	 * @param stream Output stream
9000	 * @param index  Index
9001	 **/
9002	static void writeImageUniformNameToStream(std::ostream& stream, GLuint index)
9003	{
9004		/* u_image_0 */
9005		stream << "u_image_" << index;
9006	}
9007
9008	/** Write name of variable used to store value loaded from image at given index to output stream
9009	 *
9010	 * @param stream Output stream
9011	 * @param index  Index
9012	 **/
9013	static void writeLoadedValueVariableNameToStream(std::ostream& stream, GLuint index)
9014	{
9015		/* loaded_value_0 */
9016		stream << "loaded_value_" << index;
9017	}
9018
9019	/** Write name of variable used to store coordinate of texel at given row to output stream
9020	 *
9021	 * @param stream Output stream
9022	 * @param index  Index of image uniform
9023	 * @param row    Row of image
9024	 **/
9025	static void writeCoordinatesVariableNameToStream(std::ostream& stream, GLuint index, GLuint row)
9026	{
9027		/* row_0_coordinates_0 */
9028		stream << "row_" << row << "_coordinates_" << index;
9029	}
9030
9031	struct imageUniformDeclaration
9032	{
9033		imageUniformDeclaration(GLuint index) : m_index(index)
9034		{
9035		}
9036
9037		GLuint m_index;
9038	};
9039
9040	/** Write declaration of image uniform at given index to output stream
9041	 *
9042	 * @param stream                   Output stream
9043	 * @param imageUniformDeclaration  Declaration details
9044	 *
9045	 * @return stream
9046	 **/
9047	friend std::ostream& operator<<(std::ostream& stream, const imageUniformDeclaration& declaration)
9048	{
9049		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9050		getImageUniformDeclarationDetails(declaration.m_index, format_details);
9051
9052		/* layout(r32f) uniform image2D u_image_0; */
9053		stream << "layout(" << format_details.m_image_format << ") uniform " << format_details.m_image_type << " ";
9054
9055		ImageLoadStoreMultipleUniformsTest::writeImageUniformNameToStream(stream, declaration.m_index);
9056
9057		stream << ";";
9058
9059		return stream;
9060	}
9061
9062	struct imageLoadCall
9063	{
9064		imageLoadCall(GLuint index) : m_index(index)
9065		{
9066		}
9067
9068		GLuint m_index;
9069	};
9070
9071	/* Stream operators */
9072	/** Write code that execute imageLoad routine for image at given index to output stream
9073	 *
9074	 * @param stream Output stream
9075	 * @param load   imageLoad call details
9076	 *
9077	 * @return stream
9078	 **/
9079	friend std::ostream& operator<<(std::ostream& stream, const imageLoadCall& load)
9080	{
9081		ImageLoadStoreMultipleUniformsTest::imageFormatDetails format_details;
9082		getImageUniformDeclarationDetails(load.m_index, format_details);
9083
9084		/* vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates_0); */
9085		stream << format_details.m_color_type << " ";
9086
9087		writeLoadedValueVariableNameToStream(stream, load.m_index);
9088
9089		stream << " = imageLoad(";
9090
9091		writeImageUniformNameToStream(stream, load.m_index);
9092
9093		stream << ", ";
9094
9095		writeCoordinatesVariableNameToStream(stream, load.m_index, 0 /* row */);
9096
9097		stream << ");";
9098
9099		return stream;
9100	}
9101
9102	struct imageStoreCall
9103	{
9104		imageStoreCall(GLuint index, GLuint row) : m_index(index), m_row(row)
9105		{
9106		}
9107
9108		GLuint m_index;
9109		GLuint m_row;
9110	};
9111
9112	/** Write code that execute imageStore to image at given index to output stream
9113	 *
9114	 * @param stream Output stream
9115	 * @param store  imageStore call details
9116	 *
9117	 * @return stream
9118	 **/
9119	friend std::ostream& operator<<(std::ostream& stream, const imageStoreCall& store)
9120	{
9121		/* imageStore(u_image_0, row_0_coordinates_0, -loaded_value_0); */
9122		stream << "imageStore(";
9123
9124		writeImageUniformNameToStream(stream, store.m_index);
9125
9126		stream << ", ";
9127
9128		writeCoordinatesVariableNameToStream(stream, store.m_index, store.m_row);
9129
9130		if (0 == store.m_row)
9131		{
9132			stream << ", -";
9133		}
9134		else
9135		{
9136			stream << ", ";
9137		}
9138
9139		writeLoadedValueVariableNameToStream(stream, store.m_index);
9140		stream << ");";
9141
9142		return stream;
9143	}
9144
9145	struct coordinatesVariableDeclaration
9146	{
9147		coordinatesVariableDeclaration(GLuint index, GLuint row) : m_index(index), m_row(row)
9148		{
9149		}
9150		GLuint m_index;
9151		GLuint m_row;
9152	};
9153
9154	/** Write declaration of variable for coordinate at given row to output stream
9155	 *
9156	 * @param stream      Output stream
9157	 * @param declaration Declaration details
9158	 *
9159	 * @return stream
9160	 **/
9161	friend std::ostream& operator<<(std::ostream& stream, const coordinatesVariableDeclaration& declaration)
9162	{
9163		stream << "const ivec2 ";
9164
9165		writeCoordinatesVariableNameToStream(stream, declaration.m_index, declaration.m_row);
9166
9167		stream << " = ivec2(" << declaration.m_index << ", " << declaration.m_row << ");";
9168
9169		return stream;
9170	}
9171
9172	/* Methods */
9173	/** Build program to test specified shader stage
9174	 *
9175	 * Throws exception in case of any failure
9176	 *
9177	 * @param stage Stage id
9178	 *
9179	 * @return Program id
9180	 **/
9181	GLuint buildProgramToTestShaderStage(shaderStage stage)
9182	{
9183		static const char* const boilerplate_fragment_shader_code =
9184			"#version 400 core\n"
9185			"#extension GL_ARB_shader_image_load_store : require\n"
9186			"\n"
9187			"precision highp float;\n"
9188			"\n"
9189			"void main()\n"
9190			"{\n"
9191			"    discard;\n"
9192			"}\n";
9193
9194		static const char* const boilerplate_tesselation_evaluation_shader_code =
9195			"#version 400 core\n"
9196			"#extension GL_ARB_shader_image_load_store : require\n"
9197			"\n"
9198			"precision highp float;\n"
9199			"\n"
9200			"layout(quads, equal_spacing, ccw) in;\n"
9201			"\n"
9202			"void main()\n"
9203			"{\n"
9204			"\n"
9205			"}\n";
9206
9207		static const char* const boilerplate_vertex_shader_code =
9208			"#version 400 core\n"
9209			"#extension GL_ARB_shader_image_load_store : require\n"
9210			"\n"
9211			"precision highp float;\n"
9212			"\n"
9213			"layout(location = 0) in vec4 i_position;\n"
9214			"\n"
9215			"void main()\n"
9216			"{\n"
9217			"  gl_Position = i_position;\n"
9218			"}\n";
9219
9220		const char* fragment_shader_code			   = boilerplate_fragment_shader_code;
9221		const char* geometry_shader_code			   = 0;
9222		bool		is_program_built				   = true;
9223		GLuint		program_object_id				   = 0;
9224		const char* tesselation_control_shader_code	= 0;
9225		const char* tesselation_evaluation_shader_code = 0;
9226		std::string tested_shader_stage_code;
9227		const char* vertex_shader_code = boilerplate_vertex_shader_code;
9228
9229		/* Get source code for tested shader stage */
9230		prepareShaderForTestedShaderStage(stage, tested_shader_stage_code);
9231
9232		if (true == tested_shader_stage_code.empty())
9233		{
9234			return 0;
9235		}
9236
9237		/* Set up source code for all required stages */
9238		switch (stage)
9239		{
9240		case fragmentShaderStage:
9241			fragment_shader_code = tested_shader_stage_code.c_str();
9242			break;
9243
9244		case geometryShaderStage:
9245			geometry_shader_code = tested_shader_stage_code.c_str();
9246			break;
9247
9248		case tesselationControlShaderStage:
9249			tesselation_control_shader_code	= tested_shader_stage_code.c_str();
9250			tesselation_evaluation_shader_code = boilerplate_tesselation_evaluation_shader_code;
9251			break;
9252
9253		case tesselationEvalutaionShaderStage:
9254			tesselation_evaluation_shader_code = tested_shader_stage_code.c_str();
9255			break;
9256
9257		case vertexShaderStage:
9258			vertex_shader_code = tested_shader_stage_code.c_str();
9259			break;
9260
9261		default:
9262			TCU_FAIL("Invalid shader stage");
9263		}
9264
9265		/* Build program */
9266		program_object_id =
9267			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
9268						 geometry_shader_code, fragment_shader_code, &is_program_built);
9269
9270		/* Check if program was built */
9271		if (false == is_program_built)
9272		{
9273			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
9274		}
9275
9276		/* Done */
9277		return program_object_id;
9278	}
9279
9280	/** Create texture to test given shader stage
9281	 *
9282	 * Throws exception in case of any failure
9283	 *
9284	 * @param stage Stage id
9285	 *
9286	 * @return Texture id
9287	 **/
9288	GLuint createTextureToTestShaderStage(shaderStage stage)
9289	{
9290		GLenum			   error			  = glGetError();
9291		const GLint		   max_image_uniforms = getMaximumImageUniformsForStage(stage);
9292		GLuint			   texture_id		  = 0;
9293		std::vector<GLint> texture_data;
9294
9295		const GLsizei height = 2;
9296		const GLsizei width  = max_image_uniforms;
9297
9298		if (m_min_required_image_uniforms > max_image_uniforms)
9299		{
9300			return 0;
9301		}
9302
9303		/* Generate texture id */
9304		glGenTextures(1, &texture_id);
9305		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
9306
9307		/* Bind texture */
9308		glBindTexture(GL_TEXTURE_2D, texture_id);
9309		error = glGetError();
9310		if (GL_NO_ERROR != error)
9311		{
9312			glDeleteTextures(1, &texture_id);
9313			GLU_EXPECT_NO_ERROR(error, "BindTexture");
9314		}
9315
9316		/* Prepare storage for texture data */
9317		texture_data.resize(width * height);
9318		for (GLint i = 0; i < max_image_uniforms; ++i)
9319		{
9320			texture_data[i]			= getExpectedValue(i);
9321			texture_data[i + width] = 0;
9322		}
9323
9324		/* Create first level of texture */
9325		glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, width, height, 0 /*border */, GL_RED_INTEGER, GL_INT,
9326					 &texture_data[0]);
9327		error = glGetError();
9328		if (GL_NO_ERROR != error)
9329		{
9330			glDeleteTextures(1, &texture_id);
9331			GLU_EXPECT_NO_ERROR(error, "TexImage2D");
9332		}
9333
9334		/* Make texture complete */
9335		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
9336		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
9337		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9338		error = glGetError();
9339		if (GL_NO_ERROR != error)
9340		{
9341			glDeleteTextures(1, &texture_id);
9342			GLU_EXPECT_NO_ERROR(error, "TexParameteri");
9343		}
9344
9345		/* Done */
9346		return texture_id;
9347	}
9348
9349	/** Get value of texel for image at given index
9350	 *
9351	 * @param index Index of image uniform
9352	 *
9353	 * @return Value of texel
9354	 **/
9355	GLint getExpectedValue(GLint index)
9356	{
9357		// To fix denorm issues with r32f, rg16f and r11f_g11f_b10f
9358		// we set one bit in the exponent of each component of those pixel format
9359		return 0x40104200 + index;
9360	}
9361
9362	/** Get name of uniform at given index
9363	 *
9364	 * @param index    Index of uniform
9365	 * @param out_name Name of uniform
9366	 **/
9367	void getImageUniformName(GLuint index, std::string& out_name)
9368	{
9369		std::stringstream stream;
9370
9371		writeImageUniformNameToStream(stream, index);
9372
9373		out_name = stream.str();
9374	}
9375
9376	/** Get maximum number of image uniforms allowed for given shader stage
9377	 *
9378	 * @param stage Stage id
9379	 *
9380	 * @return Maximum allowed image uniforms
9381	 **/
9382	GLint getMaximumImageUniformsForStage(shaderStage stage)
9383	{
9384		GLint  max_image_uniforms = 0;
9385		GLenum pname			  = 0;
9386
9387		switch (stage)
9388		{
9389		case fragmentShaderStage:
9390			pname = GL_MAX_FRAGMENT_IMAGE_UNIFORMS;
9391			break;
9392
9393		case geometryShaderStage:
9394			pname = GL_MAX_GEOMETRY_IMAGE_UNIFORMS;
9395			break;
9396
9397		case tesselationControlShaderStage:
9398			pname = GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS;
9399			break;
9400
9401		case tesselationEvalutaionShaderStage:
9402			pname = GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS;
9403			break;
9404
9405		case vertexShaderStage:
9406			pname = GL_MAX_VERTEX_IMAGE_UNIFORMS;
9407			break;
9408
9409		default:
9410			TCU_FAIL("Invalid shader stage");
9411		}
9412
9413		glGetIntegerv(pname, &max_image_uniforms);
9414		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
9415
9416		return max_image_uniforms;
9417	}
9418
9419	/** Prepare source for tested shader stage
9420	 *
9421	 * @param stage    Stage id
9422	 * @param out_code Source code
9423	 **/
9424	void prepareShaderForTestedShaderStage(shaderStage stage, std::string& out_code)
9425	{
9426		GLint			  max_image_uniforms	= getMaximumImageUniformsForStage(stage);
9427		const char*		  stage_specific_layout = "";
9428		const char*		  stage_specific_predicate = "true";
9429		std::stringstream stream;
9430
9431		if (m_min_required_image_uniforms > max_image_uniforms)
9432		{
9433			return;
9434		}
9435
9436		/* Expected result follows
9437		 *
9438		 * #version 400 core
9439		 * #extension GL_ARB_shader_image_load_store : require
9440		 *
9441		 * precision highp float;
9442		 *
9443		 * stage_specific_layout goes here
9444		 *
9445		 * Uniform declarations go here
9446		 *
9447		 * void main()
9448		 * {
9449		 *     const ivec2 row_0_coordinates(0, 0);
9450		 *     const ivec2 row_1_coordinates(0, 1);
9451		 *
9452		 *     For each index <0, GL_MAX_*_IMAGE_UNIFORMS>
9453		 *
9454		 *     vec4 loaded_value_0 = imageLoad(u_image_0, row_0_coordinates);
9455		 *
9456		 *     imageStore(u_image_0, row_0_coordinates, -loaded_value_0);
9457		 *     imageStore(u_image_0, row_1_coordinates, loaded_value_0);
9458		 * }
9459		 */
9460
9461		/* Get piece of code specific for stage */
9462		switch (stage)
9463		{
9464		case fragmentShaderStage:
9465			break;
9466
9467		case geometryShaderStage:
9468			stage_specific_layout = "layout(points) in;\n"
9469									"layout(points, max_vertices = 1) out;\n"
9470									"\n";
9471			break;
9472
9473		case tesselationControlShaderStage:
9474			stage_specific_layout = "layout(vertices = 4) out;\n"
9475									"\n";
9476			stage_specific_predicate = "gl_InvocationID == 0";
9477			break;
9478
9479		case tesselationEvalutaionShaderStage:
9480			stage_specific_layout = "layout(quads, equal_spacing, ccw) in;\n"
9481									"\n";
9482			break;
9483
9484		case vertexShaderStage:
9485			break;
9486
9487		default:
9488			TCU_FAIL("Invalid shader stage");
9489		}
9490
9491		/* Preamble */
9492		stream << "#version 400 core\n"
9493				  "#extension GL_ARB_shader_image_load_store : require\n"
9494				  "\n"
9495				  "precision highp float;\n"
9496				  "\n"
9497			   << stage_specific_layout;
9498
9499		/* Image uniforms declarations */
9500		for (GLint i = 0; i < max_image_uniforms; ++i)
9501		{
9502			stream << imageUniformDeclaration(i) << "\n";
9503		}
9504
9505		/* Main opening */
9506		stream << "\n"
9507				  "void main()\n"
9508				  "{\n";
9509
9510		stream << "    if (" << stage_specific_predicate << ")\n";
9511		stream << "    {\n";
9512
9513		/* imageLoad and imageStores for each uniform */
9514		for (GLint i = 0; i < max_image_uniforms; ++i)
9515		{
9516			stream << "        " << coordinatesVariableDeclaration(i, 0) << "\n"
9517				   << "        " << coordinatesVariableDeclaration(i, 1) << "\n"
9518				   << "\n"
9519				   << "        " << imageLoadCall(i) << "\n"
9520				   << "\n"
9521				   << "        " << imageStoreCall(i, 0) << "\n"
9522				   << "        " << imageStoreCall(i, 1) << "\n";
9523
9524			if (max_image_uniforms > i + 1)
9525			{
9526				stream << "\n";
9527			}
9528		}
9529
9530		stream << "    }\n";
9531
9532		/* Main closing */
9533		stream << "}\n\n";
9534
9535		/* Done */
9536		out_code = stream.str();
9537	}
9538
9539	/** Test given shader stage
9540	 *
9541	 * @param stage Stage id
9542	 *
9543	 * @return m_test_not_supported if shader stage does not support at least m_min_required_image_uniforms image uniforms;
9544	 *         testFailed when test result is negative;
9545	 *         m_test_passed when test result is positive;
9546	 **/
9547	testResult testShaderStage(shaderStage stage)
9548	{
9549		std::string		   image_uniform_name;
9550		static const GLint invalid_uniform_location = -1;
9551		const GLint		   max_image_uniforms		= getMaximumImageUniformsForStage(stage);
9552		GLenum			   primitive_mode			= GL_POINTS;
9553		GLuint			   program_id				= 0;
9554		testResult		   result					= testPassed;
9555		std::vector<GLint> texture_data;
9556		GLuint			   texture_id = 0;
9557
9558		static const GLuint height = 2;
9559		const GLuint		width  = max_image_uniforms;
9560
9561		const GLuint		positive_value_index = width;
9562		static const GLuint negated_value_index  = 0;
9563
9564		if (m_min_required_image_uniforms > max_image_uniforms)
9565		{
9566			return testNotSupported;
9567		}
9568
9569		/* Select program and texture ids for given stage */
9570		switch (stage)
9571		{
9572		case fragmentShaderStage:
9573			program_id = m_program_to_test_fs_stage_id;
9574			texture_id = m_texture_to_test_fs_stage_id;
9575			break;
9576
9577		case geometryShaderStage:
9578			program_id = m_program_to_test_gs_stage_id;
9579			texture_id = m_texture_to_test_gs_stage_id;
9580			break;
9581
9582		case tesselationControlShaderStage:
9583			primitive_mode = GL_PATCHES;
9584			program_id	 = m_program_to_test_tcs_stage_id;
9585			texture_id	 = m_texture_to_test_tcs_stage_id;
9586			break;
9587
9588		case tesselationEvalutaionShaderStage:
9589			primitive_mode = GL_PATCHES;
9590			program_id	 = m_program_to_test_tes_stage_id;
9591			texture_id	 = m_texture_to_test_tes_stage_id;
9592			break;
9593
9594		case vertexShaderStage:
9595			program_id = m_program_to_test_vs_stage_id;
9596			texture_id = m_texture_to_test_vs_stage_id;
9597			break;
9598
9599		default:
9600			TCU_FAIL("Invalid shader stage");
9601		}
9602
9603		/* Set program */
9604		glUseProgram(program_id);
9605		GLU_EXPECT_NO_ERROR(glGetError(), "UseProgram");
9606
9607		/* Bind texture to image units */
9608		for (GLint i = 0; i < max_image_uniforms; ++i)
9609		{
9610			imageFormatDetails format_details;
9611			getImageUniformDeclarationDetails(i, format_details);
9612
9613			glBindImageTexture(i /* unit */, texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
9614							   GL_READ_WRITE, format_details.m_image_unit_format);
9615			GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
9616		}
9617
9618		/* Set all image uniforms to corresponding image units */
9619		for (GLint i = 0; i < max_image_uniforms; ++i)
9620		{
9621			/* Get name */
9622			getImageUniformName(i, image_uniform_name);
9623
9624			/* Get location */
9625			GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name.c_str());
9626			GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
9627
9628			if (invalid_uniform_location == image_uniform_location)
9629			{
9630				throw tcu::InternalError("Uniform location is not available", image_uniform_name.c_str(), __FILE__,
9631										 __LINE__);
9632			}
9633
9634			/* Set uniform value */
9635			glUniform1i(image_uniform_location, i /* image_unit */);
9636			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
9637		}
9638
9639		/* Execute draw */
9640		glDrawArrays(primitive_mode, 0 /* first vertex */, 1 /* one vertex */);
9641		GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
9642
9643		glMemoryBarrier(GL_ALL_BARRIER_BITS);
9644
9645		texture_data.resize(width * height);
9646
9647		/* Get texture data */
9648		glBindTexture(GL_TEXTURE_2D, texture_id);
9649		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
9650
9651		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, &texture_data[0]);
9652		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
9653
9654		/* Verify each image uniform */
9655		for (GLint i = 0; i < max_image_uniforms; ++i)
9656		{
9657			imageFormatDetails format_details;
9658			getImageUniformDeclarationDetails(i, format_details);
9659
9660			if (false ==
9661				format_details.m_verification_routine(getExpectedValue(i), texture_data[positive_value_index + i],
9662													  texture_data[negated_value_index + i]))
9663			{
9664				m_context.getTestContext().getLog()
9665					<< tcu::TestLog::Message << "Invalid result!"
9666					<< " Image format: " << format_details.m_image_format << " Original value: "
9667					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16) << getExpectedValue(i)
9668					<< " Copied value: "
9669					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9670					<< texture_data[positive_value_index + i] << " Negated value: "
9671					<< "0x" << std::setw(8) << std::setfill('0') << std::setbase(16)
9672					<< texture_data[negated_value_index + i] << tcu::TestLog::EndMessage;
9673
9674				result = testFailed;
9675			}
9676		}
9677
9678		/* Done */
9679		return result;
9680	}
9681
9682	/** Verifies if original_value, positive_value and negated_value match
9683	 *
9684	 * @tparam T Type used during verification process, it should match float values by size
9685	 *
9686	 * @param original_value Original value of texel, used when creating a texture
9687	 * @param positive_value Value stored by shader as read
9688	 * @param negated_value  Value stored by shader after negation
9689	 *
9690	 * @return true if values match, false otherwise
9691	 **/
9692	template <typename T>
9693	static bool verifyFloat(GLint original_value, GLint positive_value, GLint negated_value)
9694	{
9695		if (original_value != positive_value)
9696		{
9697			return false;
9698		}
9699
9700		static const GLuint n_elements		  = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9701		static const GLuint sign_bit_index	= sizeof(T) * 8 - 1;		   /* 7, 15, 31 */
9702		static const T		sign_bit_mask	 = 1 << sign_bit_index;	   /* 0x80.. */
9703		static const T		sign_bit_inv_mask = (T)~sign_bit_mask;		   /* 0x7f.. */
9704
9705		const T* positive_elements = (T*)&positive_value;
9706		const T* negated_elements  = (T*)&negated_value;
9707
9708		for (GLuint i = 0; i < n_elements; ++i)
9709		{
9710			const T positive_element = positive_elements[i];
9711			const T negated_element  = negated_elements[i];
9712
9713			const T positive_sign_bit = positive_element & sign_bit_mask;
9714			const T negated_sign_bit  = negated_element & sign_bit_mask;
9715
9716			const T positive_data = positive_element & sign_bit_inv_mask;
9717			const T negated_data  = negated_element & sign_bit_inv_mask;
9718
9719			/* Compare data bits */
9720			if (positive_data != negated_data)
9721			{
9722				return false;
9723			}
9724
9725			/* Verify that sign bit is inverted */
9726			if (positive_sign_bit == negated_sign_bit)
9727			{
9728				return false;
9729			}
9730		}
9731
9732		return true;
9733	}
9734
9735	/** Verifies if original_value, positive_value and negated_value match
9736	 *
9737	 * @tparam T Type used during verification process, it should match float values by size
9738	 *
9739	 * @param original_value Original value of texel, used when creating a texture
9740	 * @param positive_value Value stored by shader as read
9741	 * @param negated_value  Value stored by shader after negation
9742	 *
9743	 * @return true if values match, false otherwise
9744	 **/
9745	template <typename T>
9746	static bool verifyFloatSignedNorm(GLint original_value, GLint positive_value, GLint negated_value)
9747	{
9748		if (original_value != positive_value)
9749		{
9750			return false;
9751		}
9752
9753		static const GLuint n_elements = sizeof(GLint) / sizeof(T); /* 1, 2, 4 */
9754
9755		const T* positive_elements = (T*)&positive_value;
9756		const T* negated_elements  = (T*)&negated_value;
9757
9758		for (GLuint i = 0; i < n_elements; ++i)
9759		{
9760			const T positive_element = positive_elements[i];
9761			const T negated_element  = negated_elements[i];
9762
9763			/* Compare data bits */
9764			if (positive_element != -negated_element)
9765			{
9766				return false;
9767			}
9768		}
9769
9770		return true;
9771	}
9772
9773	/** Verifies if original_value, positive_value and negated_value match
9774	 *
9775	 * @tparam R Number of bits for red channel
9776	 * @tparam G Number of bits for green channel
9777	 * @tparam B Number of bits for blue channel
9778	 * @tparam A Number of bits for alpha channel
9779	 *
9780	 * @param original_value Original value of texel, used when creating a texture
9781	 * @param positive_value Value stored by shader as read
9782	 * @param negated_value  Value stored by shader after negation
9783	 *
9784	 * @return true if values match, false otherwise
9785	 **/
9786	template <GLuint R, GLuint G, GLuint B, GLuint A, typename T>
9787	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9788	{
9789		if (original_value != positive_value)
9790		{
9791			return false;
9792		}
9793
9794		Integer<T, R, 0> positive_red(positive_value);
9795		Integer<T, R, 0> negated_red(negated_value);
9796
9797		Integer<T, G, R> positive_green(positive_value);
9798		Integer<T, G, R> negated_green(negated_value);
9799
9800		Integer<T, B, R + G> positive_blue(positive_value);
9801		Integer<T, B, R + G> negated_blue(negated_value);
9802
9803		Integer<T, A, R + G + B> positive_alpha(positive_value);
9804		Integer<T, A, R + G + B> negated_alpha(negated_value);
9805
9806		if (((0 != R) && (positive_red.GetNegated() != negated_red.Get())) ||
9807			((0 != B) && (positive_blue.GetNegated() != negated_blue.Get())) ||
9808			((0 != G) && (positive_green.GetNegated() != negated_green.Get())) ||
9809			((0 != A) && (positive_alpha.GetNegated() != negated_alpha.Get())))
9810		{
9811			return false;
9812		}
9813
9814		return true;
9815	}
9816
9817	/** Verifies if original_value, positive_value and negated_value match
9818	 *
9819	 * @param original_value Original value of texel, used when creating a texture
9820	 * @param positive_value Value stored by shader as read
9821	 * @param negated_value  Value stored by shader after negation
9822	 *
9823	 * @return true if values match, false otherwise
9824	 **/
9825	static bool verifyInteger(GLint original_value, GLint positive_value, GLint negated_value)
9826	{
9827		if (original_value != positive_value)
9828		{
9829			return false;
9830		}
9831
9832		if (positive_value != -negated_value)
9833		{
9834			return false;
9835		}
9836
9837		return true;
9838	}
9839
9840	/** Verifies if original_value, positive_value and negated_value match
9841	 *
9842	 * @param original_value Original value of texel, used when creating a texture
9843	 * @param positive_value Value stored by shader as read
9844	 * @param negated_value  Value stored by shader after negation
9845	 *
9846	 * @return true if values match, false otherwise
9847	 **/
9848	template <typename T>
9849	static bool verifyFloatUnsigned(GLint original_value, GLint positive_value, GLint negated_value)
9850	{
9851		if (original_value != positive_value)
9852		{
9853			return false;
9854		}
9855
9856		if (0 != negated_value)
9857		{
9858			return false;
9859		}
9860
9861		return true;
9862	}
9863};
9864
9865/** Test "Early fragment tests" description follows.
9866 *
9867 *  BasicGLSLEarlyFragTests verifies that:
9868 *  - early z test is applied when enabled,
9869 *  - early z test is not applied when disabled.
9870 *
9871 *  Proposed modifications:
9872 *  - verify that early z test does not discard all fragments when enabled,
9873 *  - verify that early stencil test is applied when enabled,
9874 *  - verify that early stencil test does not discard all fragments when
9875 *  enabled,
9876 *  - verify that early stencil test is not applied when disabled.
9877 *
9878 *  Steps:
9879 *  - prepare 2 programs that store 1.0 at red channel to image in fragment
9880 *  shader stage:
9881 *      a) one program should enable early fragment tests
9882 *      ("layout(early_fragment_tests) in;"),
9883 *      b) second program should disable early fragment tests,
9884 *  - prepare frame buffer with 64x64 R32F color and GL_DEPTH_STENCIL
9885 *  depth-stencil attachments,
9886 *  - prepare 2D texture 64x64 R32F,
9887 *  - enable depth test,
9888 *  - verify that early z test is applied when enabled:
9889 *      - use program enabling early fragment tests,
9890 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9891 *      - fill texture with zeros,
9892 *      - bind texture to image uniform,
9893 *      - draw "full screen" quad (left bottom corner at -1,-1 and right top
9894 *      corner at 1,1) at z: 0.75
9895 *      - verify that texture is still filled with zeros,
9896 *  - verify that early z test does not discard all fragments:
9897 *      - use program enabling early fragment tests,
9898 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9899 *      - fill texture with zeros,
9900 *      - bind texture to image uniform,
9901 *      - draw "full screen" quad at z: 0.25
9902 *      - verify that texture is now filled with 1.0,
9903 *  -verify that early z test is not applied when disabled:
9904 *      - use program disabling early fragment tests,
9905 *      - clean frame buffer with color: 0, stencil: 0 and depth 0.5,
9906 *      - fill texture with zeros,
9907 *      - bind texture to image uniform,
9908 *      - draw "full screen" quad at z: 0.75
9909 *      - verify that texture is now filled with 1.0.
9910 *  - disable depth test
9911 *  - enable stencil test
9912 *  - verify that early stencil test is applied when enabled:
9913 *      - use program enabling early fragment tests,
9914 *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9915 *      - fill texture with zeros,
9916 *      - set stencil test to:
9917 *          - <func> to GL_LESS,
9918 *          - <ref> to 128,
9919 *          - <mask> 0xffffffff,
9920 *      - bind texture to image uniform,
9921 *      - draw "full screen" quad at z: 0,
9922 *      - verify that texture is still filled with zeros,
9923 *  - verify that early stencil test does not discard all fragments:
9924 *      - use program enabling early fragment tests,
9925 *      - clean frame buffer with color: 0, stencil: 128 and depth 1,
9926 *      - fill texture with zeros,
9927 *      - set stencil test to:
9928 *          - <func> to GL_LESS,
9929 *          - <ref> to 0,
9930 *          - <mask> 0xffffffff,
9931 *      - bind texture to image uniform,
9932 *      - draw "full screen" quad at z: 0,
9933 *      - verify that texture is now filled with 1.0,
9934 *  - verify that early stencil test is not applied when disabled:
9935 *      - use program disabling early fragment tests,
9936 *      - clean frame buffer with color: 0, stencil: 0 and depth 1,
9937 *      - fill texture with zeros,
9938 *      - set stencil test to:
9939 *          - <func> to GL_LESS,
9940 *          - <ref> to 128,
9941 *          - <mask> 0xffffffff,
9942 *      - bind texture to image uniform,
9943 *      - draw "full screen" quad at z: 0,
9944 *      - verify that texture is now filled with 1.0
9945 **/
9946class ImageLoadStoreEarlyFragmentTestsTest : public ShaderImageLoadStoreBase
9947{
9948private:
9949	/* Constants */
9950	GLuint			   m_image_edge;
9951	static const GLint m_invalid_uniform_location = -1;
9952
9953	/* Types */
9954	/** Store id and uniform locations for a single program object
9955	 *
9956	 **/
9957	struct programDetails
9958	{
9959		GLint  m_depth_uniform_location;
9960		GLint  m_image_uniform_location;
9961		GLuint m_program_id;
9962
9963		programDetails()
9964			: m_depth_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9965			, m_image_uniform_location(ImageLoadStoreEarlyFragmentTestsTest::m_invalid_uniform_location)
9966			, m_program_id(0)
9967		{
9968			/* Nothing to be done here */
9969		}
9970	};
9971
9972	/* Fileds */
9973	/* Storage for texture data */
9974	std::vector<GLfloat> m_clean_texture_data;
9975	std::vector<GLfloat> m_extracted_texture_data;
9976
9977	/* Program details */
9978	programDetails m_disabled_early_tests;
9979	programDetails m_enabled_early_tests;
9980
9981	/* Ids of GL objects */
9982	GLuint m_color_renderbuffer_id;
9983	GLuint m_depth_stencil_renderbuffer_id;
9984	GLuint m_framebuffer_id;
9985	GLuint m_texture_id;
9986	GLuint m_vertex_array_object_id;
9987
9988public:
9989	/* Constructor */
9990	ImageLoadStoreEarlyFragmentTestsTest()
9991		: m_image_edge(0)
9992		, m_color_renderbuffer_id(0)
9993		, m_depth_stencil_renderbuffer_id(0)
9994		, m_framebuffer_id(0)
9995		, m_texture_id(0)
9996		, m_vertex_array_object_id(0)
9997	{
9998		/* Nothing to be done here */
9999	}
10000
10001	/* Methods inherited from SubcaseBase */
10002	virtual long Cleanup()
10003	{
10004		/* Restore defaults */
10005		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
10006		glBindRenderbuffer(GL_RENDERBUFFER, 0);
10007		glBindTexture(GL_TEXTURE_2D, 0);
10008		glBindVertexArray(0);
10009		glDisable(GL_DEPTH_TEST);
10010		glDisable(GL_STENCIL_TEST);
10011		glUseProgram(0);
10012
10013		/* Delete objects */
10014		if (0 != m_disabled_early_tests.m_program_id)
10015		{
10016			glDeleteProgram(m_disabled_early_tests.m_program_id);
10017			m_disabled_early_tests.m_program_id = 0;
10018		}
10019
10020		if (0 != m_enabled_early_tests.m_program_id)
10021		{
10022			glDeleteProgram(m_enabled_early_tests.m_program_id);
10023			m_enabled_early_tests.m_program_id = 0;
10024		}
10025
10026		if (0 != m_color_renderbuffer_id)
10027		{
10028			glDeleteRenderbuffers(1, &m_color_renderbuffer_id);
10029			m_color_renderbuffer_id = 0;
10030		}
10031
10032		if (0 != m_depth_stencil_renderbuffer_id)
10033		{
10034			glDeleteRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10035			m_depth_stencil_renderbuffer_id = 0;
10036		}
10037
10038		if (0 != m_framebuffer_id)
10039		{
10040			glDeleteFramebuffers(1, &m_framebuffer_id);
10041			m_framebuffer_id = 0;
10042		}
10043
10044		if (0 != m_texture_id)
10045		{
10046			glDeleteTextures(1, &m_texture_id);
10047			m_texture_id = 0;
10048		}
10049
10050		if (0 != m_vertex_array_object_id)
10051		{
10052			glDeleteVertexArrays(1, &m_vertex_array_object_id);
10053			m_vertex_array_object_id = 0;
10054		}
10055
10056		/* Done */
10057		return NO_ERROR;
10058	}
10059
10060	virtual long Run()
10061	{
10062		bool result = true;
10063
10064		/* Bind texture to first image unit */
10065		glBindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
10066						   GL_READ_WRITE, GL_R32F);
10067		GLU_EXPECT_NO_ERROR(glGetError(), "BindImageTexture");
10068
10069		/* Run tests for depth test */
10070		if (false == testEarlyZ())
10071		{
10072			result = false;
10073		}
10074
10075		/* Run tests for stencil test */
10076		if (false == testEarlyStencil())
10077		{
10078			result = false;
10079		}
10080
10081		/* Return ERROR if any problem was found */
10082		if (false == result)
10083		{
10084			return ERROR;
10085		}
10086
10087		/* Done */
10088		return NO_ERROR;
10089	}
10090
10091	virtual long Setup()
10092	{
10093		m_image_edge = de::min(64, de::min(getWindowHeight(), getWindowWidth()));
10094
10095		/* Prepare storage for texture data */
10096		m_clean_texture_data.resize(m_image_edge * m_image_edge);
10097		m_extracted_texture_data.resize(m_image_edge * m_image_edge);
10098
10099		/* Prepare programs, framebuffer and texture */
10100		buildPrograms();
10101		createFramebuffer();
10102		createTexture();
10103
10104		/* Generate vertex array object */
10105		glGenVertexArrays(1, &m_vertex_array_object_id);
10106		GLU_EXPECT_NO_ERROR(glGetError(), "GenVertexArrays");
10107
10108		/* Bind vertex array object */
10109		glBindVertexArray(m_vertex_array_object_id);
10110		GLU_EXPECT_NO_ERROR(glGetError(), "BindVertexArray");
10111
10112		/* Set clear color */
10113		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
10114		GLU_EXPECT_NO_ERROR(glGetError(), "ClearColor");
10115
10116		/* Done */
10117		return NO_ERROR;
10118	}
10119
10120private:
10121	/** Build two programs: with enabled and disabled early fragment tests
10122	 *
10123	 **/
10124	void buildPrograms()
10125	{
10126		static const char* const fragment_shader_with_disabled_early_tests =
10127			"#version 400 core\n"
10128			"#extension GL_ARB_shader_image_load_store : require\n"
10129			"\n"
10130			"precision highp float;\n"
10131			"\n"
10132			"layout(r32f) uniform image2D u_image;\n"
10133			"\n"
10134			"void main()\n"
10135			"{\n"
10136			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10137			"\n"
10138			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10139			"\n"
10140			"    discard;\n"
10141			"}\n\n";
10142
10143		static const char* const fragment_shader_with_enabled_early_tests =
10144			"#version 400 core\n"
10145			"#extension GL_ARB_shader_image_load_store : require\n"
10146			"\n"
10147			"precision highp float;\n"
10148			"\n"
10149			"layout(early_fragment_tests) in;\n"
10150			"\n"
10151			"layout(r32f) uniform image2D u_image;\n"
10152			"\n"
10153			"void main()\n"
10154			"{\n"
10155			"    vec4 color = vec4(1.0, 0, 0, 0);\n"
10156			"\n"
10157			"    imageStore(u_image, ivec2(gl_FragCoord.xy), color);\n"
10158			"\n"
10159			"    discard;\n"
10160			"}\n\n";
10161
10162		static const char* const geometry_shader_code = "#version 400 core\n"
10163														"#extension GL_ARB_shader_image_load_store : require\n"
10164														"\n"
10165														"precision highp float;\n"
10166														"\n"
10167														"layout(points)                           in;\n"
10168														"layout(triangle_strip, max_vertices = 4) out;\n"
10169														"\n"
10170														"uniform float u_depth;\n"
10171														"\n"
10172														"void main()\n"
10173														"{\n"
10174														"    // Left-bottom\n"
10175														"    gl_Position = vec4(-1, -1, u_depth, 1);\n"
10176														"    EmitVertex();\n"
10177														"\n"
10178														"    // Left-top\n"
10179														"    gl_Position = vec4(-1,  1, u_depth, 1);\n"
10180														"    EmitVertex();\n"
10181														"\n"
10182														"    // Right-bottom\n"
10183														"    gl_Position = vec4( 1, -1, u_depth, 1);\n"
10184														"    EmitVertex();\n"
10185														"\n"
10186														"    // Right-top\n"
10187														"    gl_Position = vec4( 1,  1, u_depth, 1);\n"
10188														"    EmitVertex();\n"
10189														"}\n\n";
10190
10191		static const char* const vertex_shader_code = "#version 400 core\n"
10192													  "#extension GL_ARB_shader_image_load_store : require\n"
10193													  "\n"
10194													  "precision highp float;\n"
10195													  "\n"
10196													  "void main()\n"
10197													  "{\n"
10198													  "}\n\n";
10199
10200		prepareProgramDetails(fragment_shader_with_disabled_early_tests, geometry_shader_code, vertex_shader_code,
10201							  m_disabled_early_tests);
10202
10203		prepareProgramDetails(fragment_shader_with_enabled_early_tests, geometry_shader_code, vertex_shader_code,
10204							  m_enabled_early_tests);
10205	}
10206
10207	/** Fill texture with zeros
10208	 *
10209	 **/
10210	void cleanTexture()
10211	{
10212		glTexSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, m_image_edge, m_image_edge,
10213						GL_RED, GL_FLOAT, &m_clean_texture_data[0]);
10214		GLU_EXPECT_NO_ERROR(glGetError(), "TexSubImage2D");
10215	}
10216
10217	/** Create and bind (draw) framebuffer with color and depth-stencil attachments
10218	 *
10219	 **/
10220	void createFramebuffer()
10221	{
10222		/* Generate render buffers */
10223		glGenRenderbuffers(1, &m_color_renderbuffer_id);
10224		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10225
10226		glGenRenderbuffers(1, &m_depth_stencil_renderbuffer_id);
10227		GLU_EXPECT_NO_ERROR(glGetError(), "GenRenderbuffers");
10228
10229		/* Generate and bind framebuffer object */
10230		glGenFramebuffers(1, &m_framebuffer_id);
10231		GLU_EXPECT_NO_ERROR(glGetError(), "GenFramebuffers");
10232
10233		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
10234		GLU_EXPECT_NO_ERROR(glGetError(), "BindFramebuffer");
10235
10236		/* Prepare color render buffer */
10237		glBindRenderbuffer(GL_RENDERBUFFER, m_color_renderbuffer_id);
10238		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10239
10240		glRenderbufferStorage(GL_RENDERBUFFER, GL_R32F, m_image_edge, m_image_edge);
10241		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10242
10243		/* Set up color attachment */
10244		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_color_renderbuffer_id);
10245		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10246
10247		/* Prepare depth-stencil render buffer */
10248		glBindRenderbuffer(GL_RENDERBUFFER, m_depth_stencil_renderbuffer_id);
10249		GLU_EXPECT_NO_ERROR(glGetError(), "BindRenderbuffer");
10250
10251		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_image_edge, m_image_edge);
10252		GLU_EXPECT_NO_ERROR(glGetError(), "RenderbufferStorage");
10253
10254		/* Set up depth-stencil attachment */
10255		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
10256								  m_depth_stencil_renderbuffer_id);
10257		GLU_EXPECT_NO_ERROR(glGetError(), "FramebufferRenderbuffer");
10258	}
10259
10260	/** Create 2D R32F texture
10261	 *
10262	 **/
10263	void createTexture()
10264	{
10265		glGenTextures(1, &m_texture_id);
10266		GLU_EXPECT_NO_ERROR(glGetError(), "GenTextures");
10267
10268		glBindTexture(GL_TEXTURE_2D, m_texture_id);
10269		GLU_EXPECT_NO_ERROR(glGetError(), "BindTexture");
10270
10271		glTexStorage2D(GL_TEXTURE_2D, 1, GL_R32F, m_image_edge, m_image_edge);
10272		GLU_EXPECT_NO_ERROR(glGetError(), "TexStorage2D");
10273	}
10274
10275	/** Extracts red channel from texture and verify if all texels are set to specified value
10276	 *
10277	 * @param value Expected value
10278	 *
10279	 * @return true if all texel match expected value, false otherwise
10280	 **/
10281	bool isTextureFilledWithValue(GLfloat value)
10282	{
10283		glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, &m_extracted_texture_data[0]);
10284		GLU_EXPECT_NO_ERROR(glGetError(), "GetTexImage");
10285
10286		for (GLuint i = 0; i < m_image_edge * m_image_edge; ++i)
10287		{
10288			if (value != m_extracted_texture_data[i])
10289			{
10290				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Texel at location " << i
10291													<< " has invalid value: " << m_extracted_texture_data[i]
10292													<< " expected: " << value << tcu::TestLog::EndMessage;
10293
10294				return false;
10295			}
10296		}
10297
10298		return true;
10299	}
10300
10301	/** Build program, extract location of uniforms and store results in programDetails instance
10302	 *
10303	 * Throws tcu::InternalError if uniforms are inactive
10304	 *
10305	 * @param fragment_shader_code Source of fragment shader
10306	 * @param geometry_shader_code Source of geometry shader
10307	 * @param vertex_shader_code   Source of vertex shader
10308	 * @param out_program_details  Instance of programDetails
10309	 **/
10310	void prepareProgramDetails(const char* fragment_shader_code, const char* geometry_shader_code,
10311							   const char* vertex_shader_code, programDetails& out_program_details)
10312	{
10313		static const char* const depth_uniform_name = "u_depth";
10314		static const char* const image_uniform_name = "u_image";
10315		bool					 is_program_built   = true;
10316
10317		GLuint program_id = BuildProgram(vertex_shader_code, 0 /* src_tcs */, 0 /* src_tes */, geometry_shader_code,
10318										 fragment_shader_code, &is_program_built);
10319
10320		if (false == is_program_built)
10321		{
10322			throw tcu::InternalError("Failed to build program", "", __FILE__, __LINE__);
10323		}
10324
10325		/* Get depth uniform location */
10326		GLint depth_uniform_location = glGetUniformLocation(program_id, depth_uniform_name);
10327		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10328
10329		if (m_invalid_uniform_location == depth_uniform_location)
10330		{
10331			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10332		}
10333
10334		/* Get image uniform location */
10335		GLint image_uniform_location = glGetUniformLocation(program_id, image_uniform_name);
10336		GLU_EXPECT_NO_ERROR(glGetError(), "GetUniformLocation");
10337
10338		if (m_invalid_uniform_location == image_uniform_location)
10339		{
10340			throw tcu::InternalError("Uniform is not active", image_uniform_name, __FILE__, __LINE__);
10341		}
10342
10343		/* Store results */
10344		out_program_details.m_depth_uniform_location = depth_uniform_location;
10345		out_program_details.m_image_uniform_location = image_uniform_location;
10346		out_program_details.m_program_id			 = program_id;
10347	}
10348
10349	/** Test if early fragment stencil test works as expected.
10350	 *
10351	 * @return true if successful, false otherwise
10352	 **/
10353	bool testEarlyStencil()
10354	{
10355		bool result = true;
10356
10357		glEnable(GL_STENCIL_TEST);
10358		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10359
10360		glClearDepthf(1.0f);
10361		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10362
10363		/* verify that early stencil test is applied when enabled */
10364		{
10365			glUseProgram(m_enabled_early_tests.m_program_id);
10366			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10367
10368			glClearStencil(0);
10369			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10370
10371			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10372			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10373
10374			cleanTexture();
10375
10376			glStencilFunc(GL_LESS, 128, 0xffffffff);
10377			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10378
10379			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10380			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10381
10382			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10383			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10384
10385			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10386			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10387
10388			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10389			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10390
10391			if (false == isTextureFilledWithValue(0.0f))
10392			{
10393				m_context.getTestContext().getLog() << tcu::TestLog::Message
10394													<< "Problem with early stencil test. It is not applied"
10395													<< tcu::TestLog::EndMessage;
10396
10397				result = false;
10398			}
10399		}
10400
10401		/* verify that early stencil test does not discard all fragments */
10402		{
10403			glClearStencil(128);
10404			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10405
10406			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10407			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10408
10409			cleanTexture();
10410
10411			glStencilFunc(GL_LESS, 0, 0xffffffff);
10412			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10413
10414			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10415			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10416
10417			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10418			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10419
10420			if (false == isTextureFilledWithValue(1.0f))
10421			{
10422				m_context.getTestContext().getLog()
10423					<< tcu::TestLog::Message
10424					<< "Problem with early stencil test. It discards fragments, that shall be drawn"
10425					<< tcu::TestLog::EndMessage;
10426
10427				result = false;
10428			}
10429		}
10430
10431		/* verify that early stencil test is not applied when disabled */
10432		{
10433			glUseProgram(m_disabled_early_tests.m_program_id);
10434			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10435
10436			glClearStencil(0);
10437			GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10438
10439			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10440			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10441
10442			cleanTexture();
10443
10444			glStencilFunc(GL_LESS, 128, 0xffffffff);
10445			GLU_EXPECT_NO_ERROR(glGetError(), "StencilFunc");
10446
10447			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10448			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10449
10450			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.0f /* depth */);
10451			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10452
10453			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10454			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10455
10456			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10457			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10458
10459			if (false == isTextureFilledWithValue(1.0f))
10460			{
10461				m_context.getTestContext().getLog() << tcu::TestLog::Message
10462													<< "Problem with early stencil test. It is applied when disabled"
10463													<< tcu::TestLog::EndMessage;
10464
10465				result = false;
10466			}
10467		}
10468
10469		glDisable(GL_STENCIL_TEST);
10470		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10471
10472		/* Done */
10473		return result;
10474	}
10475
10476	/** Test if early fragment depth test works as expected.
10477	 *
10478	 * @return true if successful, false otherwise
10479	 **/
10480	bool testEarlyZ()
10481	{
10482		bool result = true;
10483
10484		glEnable(GL_DEPTH_TEST);
10485		GLU_EXPECT_NO_ERROR(glGetError(), "glEnable");
10486
10487		glClearDepthf(0.5f);
10488		GLU_EXPECT_NO_ERROR(glGetError(), "ClearDepthf");
10489
10490		glClearStencil(0);
10491		GLU_EXPECT_NO_ERROR(glGetError(), "ClearStencil");
10492
10493		/* verify that early z test is applied when enabled */
10494		{
10495			glUseProgram(m_enabled_early_tests.m_program_id);
10496			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10497
10498			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10499			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10500
10501			cleanTexture();
10502
10503			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10504			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10505
10506			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10507			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10508
10509			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10510			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10511
10512			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10513			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10514
10515			if (false == isTextureFilledWithValue(0.0f))
10516			{
10517				m_context.getTestContext().getLog() << tcu::TestLog::Message
10518													<< "Problem with early z test. It is not applied"
10519													<< tcu::TestLog::EndMessage;
10520
10521				result = false;
10522			}
10523		}
10524
10525		/* verify that early z test does not discard all fragments */
10526		{
10527			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10528			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10529
10530			cleanTexture();
10531
10532			glUniform1i(m_enabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10533			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10534
10535			glUniform1f(m_enabled_early_tests.m_depth_uniform_location, -0.5f /* depth */);
10536			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10537
10538			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10539			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10540
10541			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10542			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10543
10544			if (false == isTextureFilledWithValue(1.0f))
10545			{
10546				m_context.getTestContext().getLog()
10547					<< tcu::TestLog::Message << "Problem with early z test. It discards fragments, that shall be drawn"
10548					<< tcu::TestLog::EndMessage;
10549
10550				result = false;
10551			}
10552		}
10553
10554		/* verify that early z test is not applied when disabled */
10555		{
10556			glUseProgram(m_disabled_early_tests.m_program_id);
10557			GLU_EXPECT_NO_ERROR(glGetError(), "glUseProgram");
10558
10559			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
10560			GLU_EXPECT_NO_ERROR(glGetError(), "Clear");
10561
10562			cleanTexture();
10563
10564			glUniform1i(m_disabled_early_tests.m_image_uniform_location, 0 /* first unit */);
10565			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1i");
10566
10567			glUniform1f(m_disabled_early_tests.m_depth_uniform_location, 0.5f /* depth */);
10568			GLU_EXPECT_NO_ERROR(glGetError(), "Uniform1f");
10569
10570			glDrawArrays(GL_POINTS, 0 /* first */, 1 /* number of vertices */);
10571			GLU_EXPECT_NO_ERROR(glGetError(), "DrawArrays");
10572
10573			glMemoryBarrier(GL_ALL_BARRIER_BITS);
10574			GLU_EXPECT_NO_ERROR(glGetError(), "MemoryBarrier");
10575
10576			if (false == isTextureFilledWithValue(1.0f))
10577			{
10578				m_context.getTestContext().getLog() << tcu::TestLog::Message
10579													<< "Problem with early z test. It is applied when disabled"
10580													<< tcu::TestLog::EndMessage;
10581
10582				result = false;
10583			}
10584		}
10585
10586		glDisable(GL_DEPTH_TEST);
10587		GLU_EXPECT_NO_ERROR(glGetError(), "Disable");
10588
10589		/* Done */
10590		return result;
10591	}
10592};
10593
10594//-----------------------------------------------------------------------------
10595// 4.1 NegativeUniform
10596//-----------------------------------------------------------------------------
10597class NegativeUniform : public ShaderImageLoadStoreBase
10598{
10599	GLuint m_program;
10600
10601	virtual long Setup()
10602	{
10603		m_program = 0;
10604		return NO_ERROR;
10605	}
10606
10607	virtual long Run()
10608	{
10609		const char* glsl_vs = "#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL "void main() {" NL
10610							  "  gl_Position = i_position;" NL "}";
10611		const char* glsl_fs = "#version 420 core" NL "writeonly uniform image2D g_image;" NL "void main() {" NL
10612							  "  ivec2 coord = ivec2(gl_FragCoord.xy);" NL "  imageStore(g_image, coord, vec4(0.0));" NL
10613							  "  discard;" NL "}";
10614		m_program = BuildProgram(glsl_vs, NULL, NULL, NULL, glsl_fs);
10615
10616		GLint max_image_units;
10617		glGetIntegerv(GL_MAX_IMAGE_UNITS, &max_image_units);
10618		glUseProgram(m_program);
10619
10620		glUniform1i(glGetUniformLocation(m_program, "g_image"), -1);
10621		if (glGetError() != GL_INVALID_VALUE)
10622		{
10623			m_context.getTestContext().getLog()
10624				<< tcu::TestLog::Message << "glUniform1i should generate INVALID_VALUE when <value> is less than zero."
10625				<< tcu::TestLog::EndMessage;
10626			return ERROR;
10627		}
10628		glUniform1i(glGetUniformLocation(m_program, "g_image"), max_image_units);
10629		if (glGetError() != GL_INVALID_VALUE)
10630		{
10631			m_context.getTestContext().getLog()
10632				<< tcu::TestLog::Message
10633				<< "glUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the value of "
10634				<< "MAX_IMAGE_UNITS." << tcu::TestLog::EndMessage;
10635			return ERROR;
10636		}
10637
10638		GLint i = -3;
10639		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10640		if (glGetError() != GL_INVALID_VALUE)
10641		{
10642			m_context.getTestContext().getLog()
10643				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10644				<< tcu::TestLog::EndMessage;
10645			return ERROR;
10646		}
10647		i = max_image_units + 1;
10648		glUniform1iv(glGetUniformLocation(m_program, "g_image"), 1, &i);
10649		if (glGetError() != GL_INVALID_VALUE)
10650		{
10651			m_context.getTestContext().getLog()
10652				<< tcu::TestLog::Message << "glUniform1iv should generate INVALID_VALUE when <value> is greater "
10653											"than or equal to the value of MAX_IMAGE_UNITS."
10654				<< tcu::TestLog::EndMessage;
10655			return ERROR;
10656		}
10657
10658		glUniform1ui(glGetUniformLocation(m_program, "g_image"), 0);
10659		if (glGetError() != GL_INVALID_OPERATION)
10660		{
10661			m_context.getTestContext().getLog()
10662				<< tcu::TestLog::Message
10663				<< "glUniform1iv should generate INVALID_OPERATION if the location refers to an image variable."
10664				<< tcu::TestLog::EndMessage;
10665			return ERROR;
10666		}
10667		glUniform2i(glGetUniformLocation(m_program, "g_image"), 0, 0);
10668		if (glGetError() != GL_INVALID_OPERATION)
10669		{
10670			m_context.getTestContext().getLog()
10671				<< tcu::TestLog::Message
10672				<< "glUniform2i should generate INVALID_OPERATION if the location refers to an image variable."
10673				<< tcu::TestLog::EndMessage;
10674			return ERROR;
10675		}
10676
10677		{
10678			glUseProgram(0);
10679
10680			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), -1);
10681			if (glGetError() != GL_INVALID_VALUE)
10682			{
10683				m_context.getTestContext().getLog()
10684					<< tcu::TestLog::Message
10685					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is less than zero."
10686					<< tcu::TestLog::EndMessage;
10687				return ERROR;
10688			}
10689			glProgramUniform1i(m_program, glGetUniformLocation(m_program, "g_image"), max_image_units);
10690			if (glGetError() != GL_INVALID_VALUE)
10691			{
10692				m_context.getTestContext().getLog()
10693					<< tcu::TestLog::Message
10694					<< "glProgramUniform1i should generate INVALID_VALUE when <value> is greater than or equal to the "
10695					   "value of MAX_IMAGE_UNITS."
10696					<< tcu::TestLog::EndMessage;
10697				return ERROR;
10698			}
10699
10700			GLint ii = -3;
10701			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10702			if (glGetError() != GL_INVALID_VALUE)
10703			{
10704				m_context.getTestContext().getLog()
10705					<< tcu::TestLog::Message
10706					<< "glProgramUniform1iv should generate INVALID_VALUE when <value> is less than zero."
10707					<< tcu::TestLog::EndMessage;
10708				return ERROR;
10709			}
10710			ii = max_image_units + 1;
10711			glProgramUniform1iv(m_program, glGetUniformLocation(m_program, "g_image"), 1, &ii);
10712			if (glGetError() != GL_INVALID_VALUE)
10713			{
10714				m_context.getTestContext().getLog()
10715					<< tcu::TestLog::Message << "glProgramUniform1iv should generate INVALID_VALUE when <value> "
10716												"is greater than or equal to the value of MAX_IMAGE_UNITS."
10717					<< tcu::TestLog::EndMessage;
10718				return ERROR;
10719			}
10720
10721			glProgramUniform1ui(m_program, glGetUniformLocation(m_program, "g_image"), 0);
10722			if (glGetError() != GL_INVALID_OPERATION)
10723			{
10724				m_context.getTestContext().getLog()
10725					<< tcu::TestLog::Message << "glProgramUniform1ui should generate INVALID_OPERATION if the "
10726												"location refers to an image variable."
10727					<< tcu::TestLog::EndMessage;
10728				return ERROR;
10729			}
10730			glProgramUniform2i(m_program, glGetUniformLocation(m_program, "g_image"), 0, 0);
10731			if (glGetError() != GL_INVALID_OPERATION)
10732			{
10733				m_context.getTestContext().getLog()
10734					<< tcu::TestLog::Message << "glProgramUniform2i should generate INVALID_OPERATION if the "
10735												"location refers to an image variable."
10736					<< tcu::TestLog::EndMessage;
10737				return ERROR;
10738			}
10739		}
10740
10741		return NO_ERROR;
10742	}
10743
10744	virtual long Cleanup()
10745	{
10746		glUseProgram(0);
10747		glDeleteProgram(m_program);
10748		return NO_ERROR;
10749	}
10750};
10751//-----------------------------------------------------------------------------
10752// 4.2 NegativeBind
10753//-----------------------------------------------------------------------------
10754class NegativeBind : public ShaderImageLoadStoreBase
10755{
10756	virtual long Setup()
10757	{
10758		return NO_ERROR;
10759	}
10760
10761	virtual long Run()
10762	{
10763		glBindImageTexture(100, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10764		if (glGetError() != GL_INVALID_VALUE)
10765		{
10766			m_context.getTestContext().getLog()
10767				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <unit> is "
10768											"greater than or equal to the value of MAX_IMAGE_UNITS."
10769				<< tcu::TestLog::EndMessage;
10770			return ERROR;
10771		}
10772
10773		glBindImageTexture(0, 123, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA);
10774		if (glGetError() != GL_INVALID_VALUE)
10775		{
10776			m_context.getTestContext().getLog()
10777				<< tcu::TestLog::Message << "BindImageTexture should generate INVALID_VALUE if <texture> is not "
10778											"the name of an existing texture object."
10779				<< tcu::TestLog::EndMessage;
10780			return ERROR;
10781		}
10782
10783		glBindImageTexture(1, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA + 1234);
10784		if (glGetError() != GL_INVALID_VALUE)
10785		{
10786			m_context.getTestContext().getLog()
10787				<< tcu::TestLog::Message
10788				<< "BindImageTexture should generate INVALID_VALUE if <format> is not a legal format."
10789				<< tcu::TestLog::EndMessage;
10790			return ERROR;
10791		}
10792		return NO_ERROR;
10793	}
10794
10795	virtual long Cleanup()
10796	{
10797		return NO_ERROR;
10798	}
10799};
10800//-----------------------------------------------------------------------------
10801// 4.3 NegativeCompileErrors
10802//-----------------------------------------------------------------------------
10803class NegativeCompileErrors : public ShaderImageLoadStoreBase
10804{
10805	virtual long Run()
10806	{
10807		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10808					 "layout(rgba32f) writeonly readonly uniform image2D g_image;" NL "void main() {" NL
10809					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10810			return ERROR;
10811
10812		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10813					 "layout(rgba32f) writeonly uniform image2D g_image;" NL "void main() {" NL
10814					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10815			return ERROR;
10816
10817		if (!Compile("#version 420 core" NL "in vec4 i_color;" NL "layout(location = 0) out vec4 o_color;" NL
10818					 "layout(rgba32f) readonly uniform image2D g_image;" NL "void main() {" NL
10819					 "  imageStore(g_image, ivec2(0), i_color);" NL "  o_color = i_color;" NL "}"))
10820			return ERROR;
10821
10822		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL "uniform image2D g_image;" NL
10823					 "void main() {" NL "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10824			return ERROR;
10825
10826		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10827					 "readonly uniform image2D g_image;" NL "void main() {" NL
10828					 "  o_color = imageLoad(g_image, ivec2(0));" NL "}"))
10829			return ERROR;
10830
10831		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10832					 "layout(rg16i) uniform image1D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10833			return ERROR;
10834
10835		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10836					 "layout(rg16) uniform iimage2D g_image;" NL "void main() {" NL "  o_color = vec4(1.0);" NL "}"))
10837			return ERROR;
10838
10839		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10840					 "layout(r32f) coherent uniform image2D g_image;" NL "void main() {" NL
10841					 "  imageAtomicAdd(g_image, ivec2(1), 10);" NL "  o_color = vec4(1.0);" NL "}"))
10842			return ERROR;
10843
10844		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10845					 "layout(r16i) coherent uniform iimage2D g_image;" NL "void main() {" NL
10846					 "  imageAtomicAdd(g_image, ivec2(1), 1u);" NL "  o_color = vec4(1.0);" NL "}"))
10847			return ERROR;
10848
10849		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10850					 "layout(r32ui) uniform iimage3D g_image;" NL "void main() {" NL
10851					 "  imageStore(g_image, ivec3(1), ivec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10852			return ERROR;
10853
10854		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10855					 "layout(rgba8) uniform uimage2DArray g_image;" NL "void main() {" NL
10856					 "  imageStore(g_image, ivec3(0), uvec4(1));" NL "  o_color = vec4(1.0);" NL "}"))
10857			return ERROR;
10858
10859		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10860					 "layout(rgba32f) coherent uniform image2D g_image;" NL "vec4 Load(image2D image) {" NL
10861					 "  return imageLoad(image, vec2(0));" NL "}" NL "void main() {" NL "  o_color = Load(g_image);" NL
10862					 "}"))
10863			return ERROR;
10864
10865		return NO_ERROR;
10866	}
10867
10868	bool Compile(const std::string& source)
10869	{
10870		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
10871
10872		const char* const src = source.c_str();
10873		glShaderSource(sh, 1, &src, NULL);
10874		glCompileShader(sh);
10875
10876		GLchar log[1024];
10877		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
10878		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
10879											<< log << tcu::TestLog::EndMessage;
10880
10881		GLint status;
10882		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
10883		glDeleteShader(sh);
10884
10885		if (status == GL_TRUE)
10886		{
10887			m_context.getTestContext().getLog()
10888				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
10889			return false;
10890		}
10891
10892		return true;
10893	}
10894};
10895//-----------------------------------------------------------------------------
10896// 4.4 NegativeLinkErrors
10897//-----------------------------------------------------------------------------
10898class NegativeLinkErrors : public ShaderImageLoadStoreBase
10899{
10900	virtual long Run()
10901	{
10902		if (!SupportedInVS(1))
10903			return NOT_SUPPORTED;
10904
10905		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10906				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10907				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10908				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10909				  "layout(rgba32f) uniform image2D g_image;" NL "void main() {" NL
10910				  "  imageStore(g_image, ivec2(gl_FragCoord), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10911			return ERROR;
10912
10913		if (!Link("#version 420 core" NL "layout(location = 0) in vec4 i_position;" NL
10914				  "layout(rgba32f) uniform image1D g_image;" NL "void main() {" NL
10915				  "  imageStore(g_image, gl_VertexID, vec4(0));" NL "  gl_Position = i_position;" NL "}",
10916				  "#version 420 core" NL "layout(location = 0) out vec4 o_color;" NL
10917				  "layout(rg32f) uniform image1D g_image;" NL "void main() {" NL
10918				  "  imageStore(g_image, int(gl_FragCoord.x), vec4(1.0));" NL "  o_color = vec4(1.0);" NL "}"))
10919			return ERROR;
10920
10921		return NO_ERROR;
10922	}
10923
10924	bool Link(const std::string& vs, const std::string& fs)
10925	{
10926		const GLuint p = glCreateProgram();
10927
10928		const GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
10929		glAttachShader(p, vsh);
10930		glDeleteShader(vsh);
10931		const char* const vssrc = vs.c_str();
10932		glShaderSource(vsh, 1, &vssrc, NULL);
10933		glCompileShader(vsh);
10934
10935		const GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
10936		glAttachShader(p, fsh);
10937		glDeleteShader(fsh);
10938		const char* const fssrc = fs.c_str();
10939		glShaderSource(fsh, 1, &fssrc, NULL);
10940		glCompileShader(fsh);
10941
10942		GLint status;
10943		glGetShaderiv(vsh, GL_COMPILE_STATUS, &status);
10944		if (status == GL_FALSE)
10945		{
10946			glDeleteProgram(p);
10947			m_context.getTestContext().getLog()
10948				<< tcu::TestLog::Message << "VS compilation should be ok." << tcu::TestLog::EndMessage;
10949			return false;
10950		}
10951		glGetShaderiv(fsh, GL_COMPILE_STATUS, &status);
10952		if (status == GL_FALSE)
10953		{
10954			glDeleteProgram(p);
10955			m_context.getTestContext().getLog()
10956				<< tcu::TestLog::Message << "FS compilation should be ok." << tcu::TestLog::EndMessage;
10957			return false;
10958		}
10959
10960		glLinkProgram(p);
10961
10962		GLchar log[1024];
10963		glGetProgramInfoLog(p, sizeof(log), NULL, log);
10964		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
10965											<< log << tcu::TestLog::EndMessage;
10966
10967		glGetProgramiv(p, GL_LINK_STATUS, &status);
10968		glDeleteProgram(p);
10969
10970		if (status == GL_TRUE)
10971		{
10972			m_context.getTestContext().getLog()
10973				<< tcu::TestLog::Message << "Link operation should fail." << tcu::TestLog::EndMessage;
10974			return false;
10975		}
10976
10977		return true;
10978	}
10979};
10980
10981/** Negative Test "Active image uniform limits", description follows.
10982 *
10983 *  Program that exceeds resource limits should not compile and/or link.
10984 *
10985 *  Steps:
10986 *  - try to compile and link a program that uses too many image uniforms in
10987 *  fragment shader stage,
10988 *  - try to compile and link a program that uses too many image uniforms in
10989 *  vertex shader stage,
10990 *  - try to compile and link a program that uses too many image uniforms in
10991 *  tessellation control shader stage,
10992 *  - try to compile and link a program that uses too many image uniforms in
10993 *  tessellation evaluation shader stage,
10994 *  - try to compile and link a program that uses too many image uniforms in
10995 *  geometry shader stage,
10996 *  - try to compile and link a program that uses too many image uniforms in all
10997 *  shader stages combined, any single stage should not exceed its limits, this
10998 *  step might be impossible to fulfill.
10999 *
11000 *  Test should use the following declaration of image uniforms:
11001 *  layout(r32i) uniform iimage2D u_image[N_UNIFORMS];
11002 *
11003 *  For cases where limit for single stage is tested, N_UNIFORMS should be
11004 *  defined as gl_Max*ImageUniforms + 1, where gl_Max*ImageUniforms is constant
11005 *  corresponding to tested shader stage.
11006 *
11007 *  For case where limit for combined stages is tested:
11008 *  - u_image name should be appended with the name of shader stage, like
11009 *  u_image_vertex,
11010 *  - N_UNIFORMS should be defined as gl_Max*ImageUniforms, where
11011 *  gl_Max*ImageUniforms is constant corresponding to tested shader stage,
11012 *  - compilation and linking shall succeed, when sum of all
11013 *  gl_Max*ImageUniforms corresponding to shader stages is equal (or less) to
11014 *  gl_MaxCombinedImageUniforms.
11015 *
11016 *  All defined image uniforms have to be active. Each shader stage that declare
11017 *  image uniforms should include following code snippet:
11018 *  value = 1;
11019 *  for (int i = 0; i < N_UNIFORMS; ++i)
11020 *  {
11021 *      value = imageAtomicAdd(u_image[i], coord, value);
11022 *  }
11023 **/
11024class ImageLoadStoreUniformLimitsTest : public ShaderImageLoadStoreBase
11025{
11026private:
11027	/* Fields */
11028	/* Results */
11029	bool m_result_for_combined;
11030	bool m_result_for_fragment_shader;
11031	bool m_result_for_geometry_shader;
11032	bool m_result_for_tesselation_control_shader;
11033	bool m_result_for_tesselatioon_evaluation_shader;
11034	bool m_result_for_vertex_shader;
11035
11036public:
11037	/* Constructor */
11038	ImageLoadStoreUniformLimitsTest()
11039		: m_result_for_combined(false)
11040		, m_result_for_fragment_shader(false)
11041		, m_result_for_geometry_shader(false)
11042		, m_result_for_tesselation_control_shader(false)
11043		, m_result_for_tesselatioon_evaluation_shader(false)
11044		, m_result_for_vertex_shader(false)
11045	{
11046		/* Nothing to be done */
11047	}
11048
11049	/* Methods inherited from SubcaseBase */
11050	virtual long Cleanup()
11051	{
11052		/* Done */
11053		return NO_ERROR;
11054	}
11055
11056	virtual long Run()
11057	{
11058		m_context.getTestContext().getLog() << tcu::TestLog::Message
11059											<< "This test tries to build invalid programs, expect error messages about "
11060											   "exceeded number of active image uniforms"
11061											<< tcu::TestLog::EndMessage;
11062
11063		testFragmentShaderStage();
11064		testGeometryShaderStage();
11065		testTesselationControlShaderStage();
11066		testTesselationEvaluationShaderStage();
11067		testVertexShaderStage();
11068		testCombinedShaderStages();
11069
11070		/* Return error if any stage failed */
11071		if ((false == m_result_for_combined) || (false == m_result_for_fragment_shader) ||
11072			(false == m_result_for_geometry_shader) || (false == m_result_for_tesselation_control_shader) ||
11073			(false == m_result_for_tesselatioon_evaluation_shader) || (false == m_result_for_vertex_shader))
11074		{
11075			return ERROR;
11076		}
11077
11078		/* Done */
11079		return NO_ERROR;
11080	}
11081
11082	virtual long Setup()
11083	{
11084		/* Done */
11085		return NO_ERROR;
11086	}
11087
11088private:
11089	/** Test fragment shader stage
11090	 *
11091	 **/
11092	void testFragmentShaderStage()
11093	{
11094		static const char* const fragment_shader_code =
11095			"#version 400 core\n"
11096			"#extension GL_ARB_shader_image_load_store : require\n"
11097			"\n"
11098			"precision highp float;\n"
11099			"\n"
11100			"#define N_UNIFORMS gl_MaxFragmentImageUniforms + 1\n"
11101			"\n"
11102			"flat in ivec2 vs_fs_coord;\n"
11103			"\n"
11104			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11105			"\n"
11106			"void main()\n"
11107			"{\n"
11108			"    int value = 1;\n"
11109			"\n"
11110			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11111			"    {\n"
11112			"        value = imageAtomicAdd(u_image[i], vs_fs_coord, value);\n"
11113			"    }\n"
11114			"\n"
11115			"    discard;\n"
11116			"}\n\n";
11117
11118		static const char* const vertex_shader_code = "#version 400 core\n"
11119													  "#extension GL_ARB_shader_image_load_store : require\n"
11120													  "\n"
11121													  "precision highp float;\n"
11122													  "\n"
11123													  "     in  ivec2 vs_in_coord;\n"
11124													  "flat out ivec2 vs_fs_coord;\n"
11125													  "\n"
11126													  "void main()\n"
11127													  "{\n"
11128													  "    vs_fs_coord = vs_in_coord;\n"
11129													  "}\n\n";
11130
11131		m_result_for_fragment_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11132														0 /* tesselation_control_shader_code */,
11133														0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11134
11135		if (false == m_result_for_fragment_shader)
11136		{
11137			m_context.getTestContext().getLog()
11138				<< tcu::TestLog::Message
11139				<< "Program which exceeds limit of GL_MAX_FRAGMENT_IMAGE_UNIFORMS was linked successfully."
11140				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11141				<< fragment_shader_code << tcu::TestLog::EndMessage;
11142		}
11143	}
11144
11145	/** Test geometry shader stage
11146	 *
11147	 **/
11148	void testGeometryShaderStage()
11149	{
11150		static const char* const fragment_shader_code = "#version 400 core\n"
11151														"#extension GL_ARB_shader_image_load_store : require\n"
11152														"\n"
11153														"precision highp float;\n"
11154														"\n"
11155														"void main()\n"
11156														"{\n"
11157														"    discard;\n"
11158														"}\n\n";
11159
11160		static const char* const geometry_shader_code =
11161			"#version 400 core\n"
11162			"#extension GL_ARB_shader_image_load_store : require\n"
11163			"\n"
11164			"precision highp float;\n"
11165			"\n"
11166			"layout(points)                   in;\n"
11167			"layout(points, max_vertices = 1) out;\n"
11168			"\n"
11169			"#define N_UNIFORMS gl_MaxGeometryImageUniforms + 1\n"
11170			"\n"
11171			"in ivec2 vs_gs_coord[];\n"
11172			"\n"
11173			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11174			"\n"
11175			"void main()\n"
11176			"{\n"
11177			"    int value = 1;\n"
11178			"\n"
11179			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11180			"    {\n"
11181			"        value = imageAtomicAdd(u_image[i], vs_gs_coord[0], value);\n"
11182			"    }\n"
11183			"}\n\n";
11184
11185		static const char* const vertex_shader_code = "#version 400 core\n"
11186													  "#extension GL_ARB_shader_image_load_store : require\n"
11187													  "\n"
11188													  "precision highp float;\n"
11189													  "\n"
11190													  "in  ivec2 vs_in_coord;\n"
11191													  "out ivec2 vs_gs_coord;\n"
11192													  "\n"
11193													  "void main()\n"
11194													  "{\n"
11195													  "    vs_gs_coord = vs_in_coord;\n"
11196													  "}\n\n";
11197
11198		m_result_for_geometry_shader =
11199			!doesProgramLink(fragment_shader_code, geometry_shader_code, 0 /* tesselation_control_shader_code */,
11200							 0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11201
11202		if (false == m_result_for_geometry_shader)
11203		{
11204			m_context.getTestContext().getLog()
11205				<< tcu::TestLog::Message
11206				<< "Program which exceeds limit of GL_MAX_GEOMETRY_IMAGE_UNIFORMS was linked successfully."
11207				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11208				<< geometry_shader_code << tcu::TestLog::EndMessage;
11209		}
11210	}
11211
11212	/** Test tesselation control shader stage
11213	 *
11214	 **/
11215	void testTesselationControlShaderStage()
11216	{
11217		static const char* const fragment_shader_code = "#version 400 core\n"
11218														"#extension GL_ARB_shader_image_load_store : require\n"
11219														"\n"
11220														"precision highp float;\n"
11221														"\n"
11222														"void main()\n"
11223														"{\n"
11224														"    discard;\n"
11225														"}\n\n";
11226
11227		static const char* const tesselation_control_shader_code =
11228			"#version 400 core\n"
11229			"#extension GL_ARB_shader_image_load_store : require\n"
11230			"\n"
11231			"precision highp float;\n"
11232			"\n"
11233			"layout(vertices = 4) out;\n"
11234			"\n"
11235			"#define N_UNIFORMS gl_MaxTessControlImageUniforms + 1\n"
11236			"\n"
11237			"in ivec2 vs_tcs_coord[];\n"
11238			"\n"
11239			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11240			"\n"
11241			"void main()\n"
11242			"{\n"
11243			"    int value = 1;\n"
11244			"\n"
11245			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11246			"    {\n"
11247			"        value = imageAtomicAdd(u_image[i], vs_tcs_coord[0], value);\n"
11248			"    }\n"
11249			"}\n\n";
11250
11251		static const char* const tesselation_evaluation_shader_code =
11252			"#version 400 core\n"
11253			"#extension GL_ARB_shader_image_load_store : require\n"
11254			"\n"
11255			"precision highp float;\n"
11256			"\n"
11257			"layout(quads, equal_spacing, ccw) in;\n"
11258			"\n"
11259			"void main()\n"
11260			"{\n"
11261			"}\n";
11262
11263		static const char* const vertex_shader_code = "#version 400 core\n"
11264													  "#extension GL_ARB_shader_image_load_store : require\n"
11265													  "\n"
11266													  "precision highp float;\n"
11267													  "\n"
11268													  "in  ivec2 vs_in_coord;\n"
11269													  "out ivec2 vs_tcs_coord;\n"
11270													  "\n"
11271													  "void main()\n"
11272													  "{\n"
11273													  "    vs_tcs_coord = vs_in_coord;\n"
11274													  "}\n\n";
11275
11276		m_result_for_tesselation_control_shader =
11277			!doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */, tesselation_control_shader_code,
11278							 tesselation_evaluation_shader_code, vertex_shader_code);
11279
11280		if (false == m_result_for_tesselation_control_shader)
11281		{
11282			m_context.getTestContext().getLog()
11283				<< tcu::TestLog::Message
11284				<< "Program which exceeds limit of GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS was linked successfully."
11285				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11286				<< tesselation_control_shader_code << tcu::TestLog::EndMessage;
11287		}
11288	}
11289
11290	/** Test teselation evaluation shader stage
11291	 *
11292	 **/
11293	void testTesselationEvaluationShaderStage()
11294	{
11295		static const char* const fragment_shader_code = "#version 400 core\n"
11296														"#extension GL_ARB_shader_image_load_store : require\n"
11297														"\n"
11298														"precision highp float;\n"
11299														"\n"
11300														"void main()\n"
11301														"{\n"
11302														"    discard;\n"
11303														"}\n\n";
11304
11305		static const char* const tesselation_evaluation_shader_code =
11306			"#version 400 core\n"
11307			"#extension GL_ARB_shader_image_load_store : require\n"
11308			"\n"
11309			"precision highp float;\n"
11310			"\n"
11311			"layout(quads, equal_spacing, ccw) in;\n"
11312			"\n"
11313			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms + 1\n"
11314			"\n"
11315			"in ivec2 vs_tes_coord[];\n"
11316			"\n"
11317			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11318			"\n"
11319			"void main()\n"
11320			"{\n"
11321			"    int value = 1;\n"
11322			"\n"
11323			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11324			"    {\n"
11325			"        value = imageAtomicAdd(u_image[i], vs_tes_coord[0], value);\n"
11326			"    }\n"
11327			"}\n\n";
11328
11329		static const char* const vertex_shader_code = "#version 400 core\n"
11330													  "#extension GL_ARB_shader_image_load_store : require\n"
11331													  "\n"
11332													  "precision highp float;\n"
11333													  "\n"
11334													  "in  ivec2 vs_in_coord;\n"
11335													  "out ivec2 vs_tes_coord;\n"
11336													  "\n"
11337													  "void main()\n"
11338													  "{\n"
11339													  "    vs_tes_coord = vs_in_coord;\n"
11340													  "}\n\n";
11341
11342		m_result_for_tesselatioon_evaluation_shader = !doesProgramLink(
11343			fragment_shader_code, 0 /* geometry_shader_code */, 0 /* tesselation_control_shader_code */,
11344			tesselation_evaluation_shader_code, vertex_shader_code);
11345
11346		if (false == m_result_for_tesselatioon_evaluation_shader)
11347		{
11348			m_context.getTestContext().getLog()
11349				<< tcu::TestLog::Message
11350				<< "Program which exceeds limit of GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS was linked successfully."
11351				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11352				<< tesselation_evaluation_shader_code << tcu::TestLog::EndMessage;
11353		}
11354	}
11355
11356	/** Test vertex shader stage
11357	 *
11358	 **/
11359	void testVertexShaderStage()
11360	{
11361		static const char* const fragment_shader_code = "#version 400 core\n"
11362														"#extension GL_ARB_shader_image_load_store : require\n"
11363														"\n"
11364														"precision highp float;\n"
11365														"\n"
11366														"void main()\n"
11367														"{\n"
11368														"    discard;\n"
11369														"}\n\n";
11370
11371		static const char* const vertex_shader_code =
11372			"#version 400 core\n"
11373			"#extension GL_ARB_shader_image_load_store : require\n"
11374			"\n"
11375			"precision highp float;\n"
11376			"\n"
11377			"in ivec2 vs_in_coord;\n"
11378			"\n"
11379			"#define N_UNIFORMS gl_MaxVertexImageUniforms + 1\n"
11380			"\n"
11381			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11382			"\n"
11383			"void main()\n"
11384			"{\n"
11385			"    int value = 1;\n"
11386			"\n"
11387			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11388			"    {\n"
11389			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11390			"    }\n"
11391			"}\n\n";
11392
11393		m_result_for_vertex_shader = !doesProgramLink(fragment_shader_code, 0 /* geometry_shader_code */,
11394													  0 /* tesselation_control_shader_code */,
11395													  0 /* tesselation_evaluation_shader_code */, vertex_shader_code);
11396
11397		if (false == m_result_for_vertex_shader)
11398		{
11399			m_context.getTestContext().getLog()
11400				<< tcu::TestLog::Message
11401				<< "Program which exceeds limit of GL_MAX_VERTEX_IMAGE_UNIFORMS was linked successfully."
11402				<< " File: " << __FILE__ << " Line: " << __LINE__ << " Shader code:\n"
11403				<< vertex_shader_code << tcu::TestLog::EndMessage;
11404		}
11405	}
11406
11407	/** Test combined shader stages
11408	 *
11409	 **/
11410	void testCombinedShaderStages()
11411	{
11412		std::string fragment_shader_code =
11413			"#version 400 core\n"
11414			"#extension GL_ARB_shader_image_load_store : require\n"
11415			"\n"
11416			"precision highp float;\n"
11417			"\n"
11418			"#define N_UNIFORMS gl_MaxFragmentImageUniforms\n"
11419			"\n"
11420			"flat in ivec2 gs_fs_coord;\n"
11421			"\n"
11422			"layout(r32i) uniform iimage2D u_image_fragment[N_UNIFORMS];\n"
11423			"\n"
11424			"void main()\n"
11425			"{\n"
11426			"    int value = 1;\n"
11427			"\n"
11428			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11429			"    {\n"
11430			"        value = imageAtomicAdd(u_image_fragment[i], gs_fs_coord, value);\n"
11431			"    }\n"
11432			"\n"
11433			"    discard;\n"
11434			"}\n\n";
11435
11436		std::string geometry_shader_code =
11437			"#version 400 core\n"
11438			"#extension GL_ARB_shader_image_load_store : require\n"
11439			"\n"
11440			"precision highp float;\n"
11441			"\n"
11442			"layout(points)                   in;\n"
11443			"layout(points, max_vertices = 1) out;\n"
11444			"\n"
11445			"#define N_UNIFORMS gl_MaxGeometryImageUniforms\n"
11446			"\n"
11447			"flat in  ivec2 tes_gs_coord[];\n"
11448			"flat out ivec2 gs_fs_coord;\n"
11449			"\n"
11450			"#ifdef IMAGES\n"
11451			"layout(r32i) uniform iimage2D u_image_geometry[N_UNIFORMS];\n"
11452			"#endif\n"
11453			"\n"
11454			"void main()\n"
11455			"{\n"
11456			"#ifdef IMAGES\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_geometry[i], tes_gs_coord[0], value);\n"
11462			"    }\n"
11463			"\n"
11464			"#endif\n"
11465			"    gs_fs_coord = tes_gs_coord[0];\n"
11466			"    EmitVertex();\n"
11467			"}\n\n";
11468
11469		std::string tesselation_control_shader_code =
11470			"#version 400 core\n"
11471			"#extension GL_ARB_shader_image_load_store : require\n"
11472			"\n"
11473			"precision highp float;\n"
11474			"\n"
11475			"layout(vertices = 4) out;\n"
11476			"\n"
11477			"#define N_UNIFORMS gl_MaxTessControlImageUniforms\n"
11478			"\n"
11479			"flat in  ivec2 vs_tcs_coord[];\n"
11480			"flat out ivec2 tcs_tes_coord[];\n"
11481			"\n"
11482			"#ifdef IMAGES\n"
11483			"layout(r32i) uniform iimage2D u_image_tess_control[N_UNIFORMS];\n"
11484			"#endif\n"
11485			"\n"
11486			"void main()\n"
11487			"{\n"
11488			"#ifdef IMAGES\n"
11489			"    int value = 1;\n"
11490			"\n"
11491			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11492			"    {\n"
11493			"        value = imageAtomicAdd(u_image_tess_control[i], vs_tcs_coord[0], value);\n"
11494			"    }\n"
11495			"\n"
11496			"#endif\n"
11497			"    tcs_tes_coord[gl_InvocationID] = vs_tcs_coord[0];\n"
11498			"}\n\n";
11499
11500		std::string tesselation_evaluation_shader_code =
11501			"#version 400 core\n"
11502			"#extension GL_ARB_shader_image_load_store : require\n"
11503			"\n"
11504			"precision highp float;\n"
11505			"\n"
11506			"layout(quads, equal_spacing, ccw) in;\n"
11507			"\n"
11508			"#define N_UNIFORMS gl_MaxTessEvaluationImageUniforms\n"
11509			"\n"
11510			"flat in  ivec2 tcs_tes_coord[];\n"
11511			"flat out ivec2 tes_gs_coord;\n"
11512			"\n"
11513			"#ifdef IMAGES\n"
11514			"layout(r32i) uniform iimage2D u_image_tess_evaluation[N_UNIFORMS];\n"
11515			"#endif\n"
11516			"\n"
11517			"void main()\n"
11518			"{\n"
11519			"#ifdef IMAGES\n"
11520			"    int value = 1;\n"
11521			"\n"
11522			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11523			"    {\n"
11524			"        value = imageAtomicAdd(u_image_tess_evaluation[i], tcs_tes_coord[0], value);\n"
11525			"    }\n"
11526			"\n"
11527			"#endif\n"
11528			"    tes_gs_coord = tcs_tes_coord[0];\n"
11529			"}\n\n";
11530
11531		std::string vertex_shader_code =
11532			"#version 400 core\n"
11533			"#extension GL_ARB_shader_image_load_store : require\n"
11534			"\n"
11535			"precision highp float;\n"
11536			"\n"
11537			"     in  ivec2 vs_in_coord;\n"
11538			"flat out ivec2 vs_tcs_coord;\n"
11539			"\n"
11540			"#define N_UNIFORMS gl_MaxVertexImageUniforms\n"
11541			"\n"
11542			"#ifdef IMAGES\n"
11543			"layout(r32i) uniform iimage2D u_image[N_UNIFORMS];\n"
11544			"#endif\n"
11545			"\n"
11546			"void main()\n"
11547			"{\n"
11548			"#ifdef IMAGES\n"
11549			"    int value = 1;\n"
11550			"\n"
11551			"    for (int i = 0; i < N_UNIFORMS; ++i)\n"
11552			"    {\n"
11553			"        value = imageAtomicAdd(u_image[i], vs_in_coord, value);\n"
11554			"    }\n"
11555			"\n"
11556			"#endif\n"
11557			"    vs_tcs_coord = vs_tcs_coord;\n"
11558			"}\n\n";
11559
11560		/* Active image uniform limits */
11561		GLint max_combined_image_uniforms				= 0;
11562		GLint max_fragment_image_uniforms				= 0;
11563		GLint max_geometry_image_uniforms				= 0;
11564		GLint max_tesselation_control_image_uniforms	= 0;
11565		GLint max_tesselation_evaluation_image_uniforms = 0;
11566		GLint max_vertex_image_uniforms					= 0;
11567
11568		/* Get limit values */
11569		glGetIntegerv(GL_MAX_COMBINED_IMAGE_UNIFORMS, &max_combined_image_uniforms);
11570		glGetIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &max_fragment_image_uniforms);
11571		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &max_geometry_image_uniforms);
11572		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &max_tesselation_control_image_uniforms);
11573		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &max_tesselation_evaluation_image_uniforms);
11574		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &max_vertex_image_uniforms);
11575		GLU_EXPECT_NO_ERROR(glGetError(), "GetIntegerv");
11576
11577		if (max_vertex_image_uniforms)
11578			vertex_shader_code.insert(18, "#define IMAGES\n");
11579		if (max_geometry_image_uniforms)
11580			geometry_shader_code.insert(18, "#define IMAGES\n");
11581		if (max_tesselation_control_image_uniforms)
11582			tesselation_control_shader_code.insert(18, "#define IMAGES\n");
11583		if (max_tesselation_evaluation_image_uniforms)
11584			tesselation_evaluation_shader_code.insert(18, "#define IMAGES\n");
11585
11586		/* Check if program builds */
11587		m_result_for_combined =
11588			!doesProgramLink(fragment_shader_code.c_str(),
11589							 geometry_shader_code.c_str(),
11590							 tesselation_control_shader_code.c_str(),
11591							 tesselation_evaluation_shader_code.c_str(),
11592							 vertex_shader_code.c_str());
11593
11594		/* Result depends on the limit values */
11595		if (max_combined_image_uniforms >=
11596			(max_fragment_image_uniforms + max_geometry_image_uniforms + max_tesselation_control_image_uniforms +
11597			 max_tesselation_evaluation_image_uniforms + max_vertex_image_uniforms))
11598		{
11599			/* In this case, combined image uniforms limit cannot be exeeded, therefore successful linking is expected */
11600			m_result_for_combined = !m_result_for_combined;
11601
11602			if (false == m_result_for_combined)
11603			{
11604				m_context.getTestContext().getLog()
11605					<< tcu::TestLog::Message << "There was an error while building a program."
11606					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11607					<< vertex_shader_code << "\nTesselation control shader code:\n"
11608					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11609					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11610					<< geometry_shader_code << "\nFragment shader code:\n"
11611					<< fragment_shader_code << tcu::TestLog::EndMessage;
11612			}
11613		}
11614		else
11615		{
11616			/* In this case, combined image uniforms can be exceeded, therefore failed linking is expected */
11617			if (false == m_result_for_combined)
11618			{
11619				m_context.getTestContext().getLog()
11620					<< tcu::TestLog::Message
11621					<< "Program which exceeds limit of GL_MAX_COMBINED_IMAGE_UNIFORMS was linked successfully."
11622					<< " File: " << __FILE__ << " Line: " << __LINE__ << " Vertex shader code:\n"
11623					<< vertex_shader_code << "\nTesselation control shader code:\n"
11624					<< tesselation_control_shader_code << "\nTesselation evaluation shader code:\n"
11625					<< tesselation_evaluation_shader_code << "\nGeometry shader code:\n"
11626					<< geometry_shader_code << "\nFragment shader code:\n"
11627					<< fragment_shader_code << tcu::TestLog::EndMessage;
11628			}
11629		}
11630	}
11631
11632	/** Check if program builds successfully
11633	 *
11634	 * @param fragment_shader_code               Source code for fragment shader stage
11635	 * @param geometry_shader_code               Source code for geometry shader stage
11636	 * @param tesselation_control_shader_code    Source code for tesselation control shader stage
11637	 * @param tesselation_evaluation_shader_code Source code for tesselation evaluation shader stage
11638	 * @param vertex_shader_code                 Source code for vertex shader stage
11639	 *
11640	 * @return true if program was built without errors, false otherwise
11641	 **/
11642	bool doesProgramLink(const char* fragment_shader_code, const char* geometry_shader_code,
11643						 const char* tesselation_control_shader_code, const char* tesselation_evaluation_shader_code,
11644						 const char* vertex_shader_code)
11645	{
11646		bool   is_program_built = true;
11647		GLuint program_id		= 0;
11648
11649		program_id =
11650			BuildProgram(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
11651						 geometry_shader_code, fragment_shader_code, &is_program_built);
11652
11653		if (0 != program_id)
11654		{
11655			glDeleteProgram(program_id);
11656		}
11657
11658		return is_program_built;
11659	}
11660};
11661}
11662
11663ShaderImageLoadStoreTests::ShaderImageLoadStoreTests(deqp::Context& context)
11664	: TestCaseGroup(context, "shader_image_load_store", "")
11665{
11666}
11667
11668ShaderImageLoadStoreTests::~ShaderImageLoadStoreTests(void)
11669{
11670}
11671
11672void ShaderImageLoadStoreTests::init()
11673{
11674	using namespace deqp;
11675	addChild(new TestSubcase(m_context, "basic-api-get", TestSubcase::Create<BasicAPIGet>));
11676	addChild(new TestSubcase(m_context, "basic-api-bind", TestSubcase::Create<BasicAPIBind>));
11677	addChild(new TestSubcase(m_context, "basic-api-barrier", TestSubcase::Create<BasicAPIBarrier>));
11678	addChild(new TestSubcase(m_context, "basic-api-texParam", TestSubcase::Create<BasicAPITexParam>));
11679	addChild(new TestSubcase(m_context, "basic-allFormats-store", TestSubcase::Create<BasicAllFormatsStore>));
11680	addChild(new TestSubcase(m_context, "basic-allFormats-load", TestSubcase::Create<BasicAllFormatsLoad>));
11681	addChild(new TestSubcase(m_context, "basic-allFormats-storeGeometryStages",
11682							 TestSubcase::Create<BasicAllFormatsStoreGeometryStages>));
11683	addChild(new TestSubcase(m_context, "basic-allFormats-loadGeometryStages",
11684							 TestSubcase::Create<BasicAllFormatsLoadGeometryStages>));
11685	addChild(new TestSubcase(m_context, "basic-allFormats-loadStoreComputeStage",
11686							 TestSubcase::Create<BasicAllFormatsLoadStoreComputeStage>));
11687	addChild(new TestSubcase(m_context, "basic-allTargets-store", TestSubcase::Create<BasicAllTargetsStore>));
11688	addChild(new TestSubcase(m_context, "basic-allTargets-load-nonMS", TestSubcase::Create<BasicAllTargetsLoadNonMS>));
11689	addChild(new TestSubcase(m_context, "basic-allTargets-load-ms", TestSubcase::Create<BasicAllTargetsLoadMS>));
11690	addChild(new TestSubcase(m_context, "basic-allTargets-atomic", TestSubcase::Create<BasicAllTargetsAtomic>));
11691	addChild(
11692		new TestSubcase(m_context, "basic-allTargets-loadStoreVS", TestSubcase::Create<BasicAllTargetsLoadStoreVS>));
11693	addChild(
11694		new TestSubcase(m_context, "basic-allTargets-loadStoreTCS", TestSubcase::Create<BasicAllTargetsLoadStoreTCS>));
11695	addChild(
11696		new TestSubcase(m_context, "basic-allTargets-loadStoreTES", TestSubcase::Create<BasicAllTargetsLoadStoreTES>));
11697	addChild(
11698		new TestSubcase(m_context, "basic-allTargets-loadStoreGS", TestSubcase::Create<BasicAllTargetsLoadStoreGS>));
11699	addChild(
11700		new TestSubcase(m_context, "basic-allTargets-loadStoreCS", TestSubcase::Create<BasicAllTargetsLoadStoreCS>));
11701	addChild(new TestSubcase(m_context, "basic-allTargets-atomicVS", TestSubcase::Create<BasicAllTargetsAtomicVS>));
11702	addChild(new TestSubcase(m_context, "basic-allTargets-atomicTCS", TestSubcase::Create<BasicAllTargetsAtomicTCS>));
11703	addChild(new TestSubcase(m_context, "basic-allTargets-atomicGS", TestSubcase::Create<BasicAllTargetsAtomicGS>));
11704	addChild(new TestSubcase(m_context, "basic-allTargets-atomicCS", TestSubcase::Create<BasicAllTargetsAtomicCS>));
11705	addChild(new TestSubcase(m_context, "basic-glsl-misc", TestSubcase::Create<BasicGLSLMisc>));
11706	addChild(new TestSubcase(m_context, "basic-glsl-earlyFragTests", TestSubcase::Create<BasicGLSLEarlyFragTests>));
11707	addChild(new TestSubcase(m_context, "basic-glsl-const", TestSubcase::Create<BasicGLSLConst>));
11708	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess", TestSubcase::Create<AdvancedSyncImageAccess>));
11709	addChild(new TestSubcase(m_context, "advanced-sync-vertexArray", TestSubcase::Create<AdvancedSyncVertexArray>));
11710	addChild(new TestSubcase(m_context, "advanced-sync-drawIndirect", TestSubcase::Create<AdvancedSyncDrawIndirect>));
11711	addChild(new TestSubcase(m_context, "advanced-sync-textureUpdate", TestSubcase::Create<AdvancedSyncTextureUpdate>));
11712	addChild(new TestSubcase(m_context, "advanced-sync-imageAccess2", TestSubcase::Create<AdvancedSyncImageAccess2>));
11713	addChild(new TestSubcase(m_context, "advanced-sync-bufferUpdate", TestSubcase::Create<AdvancedSyncBufferUpdate>));
11714	addChild(new TestSubcase(m_context, "advanced-allStages-oneImage", TestSubcase::Create<AdvancedAllStagesOneImage>));
11715	addChild(new TestSubcase(m_context, "advanced-memory-dependentInvocation",
11716							 TestSubcase::Create<AdvancedMemoryDependentInvocation>));
11717	addChild(new TestSubcase(m_context, "advanced-memory-order", TestSubcase::Create<AdvancedMemoryOrder>));
11718	addChild(new TestSubcase(m_context, "advanced-sso-simple", TestSubcase::Create<AdvancedSSOSimple>));
11719	addChild(new TestSubcase(m_context, "advanced-sso-atomicCounters", TestSubcase::Create<AdvancedSSOAtomicCounters>));
11720	addChild(new TestSubcase(m_context, "advanced-sso-subroutine", TestSubcase::Create<AdvancedSSOSubroutine>));
11721	addChild(new TestSubcase(m_context, "advanced-sso-perSample", TestSubcase::Create<AdvancedSSOPerSample>));
11722	addChild(new TestSubcase(m_context, "advanced-copyImage", TestSubcase::Create<AdvancedCopyImage>));
11723	addChild(new TestSubcase(m_context, "advanced-allMips", TestSubcase::Create<AdvancedAllMips>));
11724	addChild(new TestSubcase(m_context, "advanced-cast", TestSubcase::Create<AdvancedCast>));
11725	addChild(
11726		new TestSubcase(m_context, "single-byte_data_alignment", TestSubcase::Create<ImageLoadStoreDataAlignmentTest>));
11727	addChild(
11728		new TestSubcase(m_context, "non-layered_binding", TestSubcase::Create<ImageLoadStoreNonLayeredBindingTest>));
11729	addChild(
11730		new TestSubcase(m_context, "incomplete_textures", TestSubcase::Create<ImageLoadStoreIncompleteTexturesTest>));
11731	addChild(new TestSubcase(m_context, "multiple-uniforms", TestSubcase::Create<ImageLoadStoreMultipleUniformsTest>));
11732	addChild(
11733		new TestSubcase(m_context, "early-fragment-tests", TestSubcase::Create<ImageLoadStoreEarlyFragmentTestsTest>));
11734	addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
11735	addChild(new TestSubcase(m_context, "negative-bind", TestSubcase::Create<NegativeBind>));
11736	addChild(new TestSubcase(m_context, "negative-compileErrors", TestSubcase::Create<NegativeCompileErrors>));
11737	addChild(new TestSubcase(m_context, "negative-linkErrors", TestSubcase::Create<NegativeLinkErrors>));
11738	addChild(new TestSubcase(m_context, "uniform-limits", TestSubcase::Create<ImageLoadStoreUniformLimitsTest>));
11739}
11740}
11741