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