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 "gl4cShaderImageSizeTests.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
33namespace gl4cts
34{
35using namespace glw;
36
37namespace
38{
39typedef tcu::Vec3  vec3;
40typedef tcu::Vec4  vec4;
41typedef tcu::IVec4 ivec4;
42typedef tcu::UVec4 uvec4;
43
44class ShaderImageSizeBase : public deqp::SubcaseBase
45{
46	virtual std::string Title()
47	{
48		return "";
49	}
50
51	virtual std::string Purpose()
52	{
53		return "";
54	}
55
56	virtual std::string Method()
57	{
58		return "";
59	}
60
61	virtual std::string PassCriteria()
62	{
63		return "";
64	}
65
66public:
67	bool SupportedInVS(int requiredVS)
68	{
69		GLint imagesVS;
70		glGetIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &imagesVS);
71		if (imagesVS >= requiredVS)
72			return true;
73		else
74		{
75			std::ostringstream reason;
76			reason << "Required " << requiredVS << " VS image uniforms but only " << imagesVS << " available."
77				   << std::endl;
78			OutputNotSupported(reason.str());
79			return false;
80		}
81	}
82
83	bool SupportedInTCS(int requiredTCS)
84	{
85		GLint imagesTCS;
86		glGetIntegerv(GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS, &imagesTCS);
87		if (imagesTCS >= requiredTCS)
88			return true;
89		else
90		{
91			std::ostringstream reason;
92			reason << "Required " << requiredTCS << " TCS image uniforms but only " << imagesTCS << " available."
93				   << std::endl;
94			OutputNotSupported(reason.str());
95			return false;
96		}
97	}
98
99	bool SupportedInTES(int requiredTES)
100	{
101		GLint imagesTES;
102		glGetIntegerv(GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, &imagesTES);
103		if (imagesTES >= requiredTES)
104			return true;
105		else
106		{
107			std::ostringstream reason;
108			reason << "Required " << requiredTES << " TES image uniforms but only " << imagesTES << " available."
109				   << std::endl;
110			OutputNotSupported(reason.str());
111			return false;
112		}
113	}
114
115	bool SupportedInGS(int requiredGS)
116	{
117		GLint imagesGS;
118		glGetIntegerv(GL_MAX_GEOMETRY_IMAGE_UNIFORMS, &imagesGS);
119		if (imagesGS >= requiredGS)
120			return true;
121		else
122		{
123			std::ostringstream reason;
124			reason << "Required " << requiredGS << " GS image uniforms but only " << imagesGS << " available."
125				   << std::endl;
126			OutputNotSupported(reason.str());
127			return false;
128		}
129	}
130
131	bool SupportedInStage(int stage, int required)
132	{
133		switch (stage)
134		{
135		case 0:
136			return SupportedInVS(required);
137		case 1:
138			return SupportedInTCS(required);
139		case 2:
140			return SupportedInTES(required);
141		case 3:
142			return SupportedInGS(required);
143		default:
144			return true;
145		}
146	}
147
148	bool SupportedSamples(int required)
149	{
150		int i;
151		glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &i);
152		if (i >= required)
153			return true;
154		else
155		{
156			std::ostringstream reason;
157			reason << "Required " << required << " image samples but only " << i << " available." << std::endl;
158			OutputNotSupported(reason.str());
159			return false;
160		}
161	}
162
163	int getWindowWidth()
164	{
165		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
166		return renderTarget.getWidth();
167	}
168
169	int getWindowHeight()
170	{
171		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
172		return renderTarget.getHeight();
173	}
174
175	inline bool ColorEqual(const vec4& c0, const vec4& c1, const vec4& epsilon)
176	{
177		if (fabs(c0[0] - c1[0]) > epsilon[0])
178			return false;
179		if (fabs(c0[1] - c1[1]) > epsilon[1])
180			return false;
181		if (fabs(c0[2] - c1[2]) > epsilon[2])
182			return false;
183		if (fabs(c0[3] - c1[3]) > epsilon[3])
184			return false;
185		return true;
186	}
187
188	template <class T>
189	std::string ToString(T v)
190	{
191		std::ostringstream s;
192		s << "[";
193		for (int i = 0; i < 4; ++i)
194			s << v[i] << (i == 3 ? "" : ",");
195		s << "]";
196		return s.str();
197	}
198
199	bool ValidateReadBuffer(int x, int y, int w, int h, const vec4& expected)
200	{
201		bool					 status		  = true;
202		const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
203		const tcu::PixelFormat&  pixelFormat  = renderTarget.getPixelFormat();
204		vec4					 g_color_eps  = vec4(
205			1.f / static_cast<float>(1 << pixelFormat.redBits), 1.f / static_cast<float>(1 << pixelFormat.greenBits),
206			1.f / static_cast<float>(1 << pixelFormat.blueBits), 1.f / static_cast<float>(1 << pixelFormat.alphaBits));
207
208		std::vector<vec4> fb(w * h);
209		glReadPixels(x, y, w, h, GL_RGBA, GL_FLOAT, &fb[0]);
210
211		for (int yy = 0; yy < h; ++yy)
212		{
213			for (int xx = 0; xx < w; ++xx)
214			{
215				const int idx = yy * w + xx;
216				if (!ColorEqual(fb[idx], expected, g_color_eps))
217				{
218					m_context.getTestContext().getLog()
219						<< tcu::TestLog::Message << "First bad color: " << ToString(fb[idx])
220						<< tcu::TestLog::EndMessage;
221					status = false;
222					return status;
223				}
224			}
225		}
226		return status;
227	}
228
229	bool CheckProgram(GLuint program)
230	{
231		if (program == 0)
232			return true;
233		GLint status;
234		glGetProgramiv(program, GL_LINK_STATUS, &status);
235
236		if (status == GL_FALSE)
237		{
238			GLint attached_shaders;
239			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
240
241			if (attached_shaders > 0)
242			{
243				std::vector<GLuint> shaders(attached_shaders);
244				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
245
246				for (GLint i = 0; i < attached_shaders; ++i)
247				{
248					GLenum type;
249					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
250					switch (type)
251					{
252					case GL_VERTEX_SHADER:
253						m_context.getTestContext().getLog()
254							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
255						break;
256					case GL_TESS_CONTROL_SHADER:
257						m_context.getTestContext().getLog()
258							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
259							<< tcu::TestLog::EndMessage;
260						break;
261					case GL_TESS_EVALUATION_SHADER:
262						m_context.getTestContext().getLog()
263							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
264							<< tcu::TestLog::EndMessage;
265						break;
266					case GL_GEOMETRY_SHADER:
267						m_context.getTestContext().getLog()
268							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
269						break;
270					case GL_FRAGMENT_SHADER:
271						m_context.getTestContext().getLog()
272							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
273						break;
274					case GL_COMPUTE_SHADER:
275						m_context.getTestContext().getLog()
276							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
277						break;
278					default:
279						m_context.getTestContext().getLog()
280							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
281						break;
282					}
283					GLint length;
284					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
285					if (length > 0)
286					{
287						std::vector<GLchar> source(length);
288						glGetShaderSource(shaders[i], length, NULL, &source[0]);
289						m_context.getTestContext().getLog()
290							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
291					}
292					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
293					if (length > 0)
294					{
295						std::vector<GLchar> log(length);
296						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
297						m_context.getTestContext().getLog()
298							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
299					}
300				}
301			}
302			GLint length;
303			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
304			if (length > 0)
305			{
306				std::vector<GLchar> log(length);
307				glGetProgramInfoLog(program, length, NULL, &log[0]);
308				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
309			}
310		}
311		return status == GL_TRUE ? true : false;
312	}
313};
314
315template <typename T>
316std::string ImageTypePrefix();
317
318template <>
319std::string ImageTypePrefix<vec4>()
320{
321	return "";
322}
323
324template <>
325std::string ImageTypePrefix<ivec4>()
326{
327	return "i";
328}
329
330template <>
331std::string ImageTypePrefix<uvec4>()
332{
333	return "u";
334}
335
336template <typename T>
337std::string ImageFormatPostfix();
338
339template <>
340std::string ImageFormatPostfix<vec4>()
341{
342	return "f";
343}
344
345template <>
346std::string ImageFormatPostfix<ivec4>()
347{
348	return "i";
349}
350
351template <>
352std::string ImageFormatPostfix<uvec4>()
353{
354	return "ui";
355}
356
357template <typename T>
358GLenum TexInternalFormat();
359
360template <>
361GLenum TexInternalFormat<vec4>()
362{
363	return GL_RGBA32F;
364}
365
366template <>
367GLenum TexInternalFormat<ivec4>()
368{
369	return GL_RGBA32I;
370}
371
372template <>
373GLenum TexInternalFormat<uvec4>()
374{
375	return GL_RGBA32UI;
376}
377
378template <typename T>
379GLenum TexType();
380
381template <>
382GLenum TexType<vec4>()
383{
384	return GL_FLOAT;
385}
386
387template <>
388GLenum TexType<ivec4>()
389{
390	return GL_INT;
391}
392
393template <>
394GLenum TexType<uvec4>()
395{
396	return GL_UNSIGNED_INT;
397}
398
399template <typename T>
400GLenum TexFormat();
401
402template <>
403GLenum TexFormat<vec4>()
404{
405	return GL_RGBA;
406}
407
408template <>
409GLenum TexFormat<ivec4>()
410{
411	return GL_RGBA_INTEGER;
412}
413
414template <>
415GLenum TexFormat<uvec4>()
416{
417	return GL_RGBA_INTEGER;
418}
419//=============================================================================
420// ImageSizeMachine
421//-----------------------------------------------------------------------------
422class ImageSizeMachine : public deqp::GLWrapper
423{
424	GLuint m_pipeline;
425	GLuint m_program[3];
426	GLuint m_vertex_array;
427	GLuint m_texture;
428
429	template <typename T>
430	std::string GenShader(int stage, bool ms_and_1d, bool subroutine)
431	{
432		std::ostringstream os;
433		os << "#version 430 core";
434		if (stage == 4)
435		{ // CS
436			os << NL "#extension GL_ARB_compute_shader : require";
437		}
438		os << NL "layout(binding = 0, rgba32i) writeonly uniform iimage2D g_result;";
439		if (ms_and_1d == false)
440		{
441			os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
442			   << "image2D g_image_2d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform "
443			   << ImageTypePrefix<T>() << "image3D g_image_3d;" NL "layout(binding = 3, rgba32"
444			   << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
445			   << "image2D g_image_cube;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform "
446			   << ImageTypePrefix<T>() << "imageCubeArray g_image_cube_array;" NL "layout(binding = 5, rgba32"
447			   << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
448			   << "image2DRect g_image_rect;" NL "layout(binding = 6, rgba32" << ImageFormatPostfix<T>() << ") uniform "
449			   << ImageTypePrefix<T>() << "image2DArray g_image_2d_array;" NL "layout(binding = 7, rgba32"
450			   << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>() << "imageBuffer g_image_buffer;";
451		}
452		else
453		{
454			os << NL "layout(binding = 1, rgba32" << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
455			   << "image1D g_image_1d;" NL "layout(binding = 2, rgba32" << ImageFormatPostfix<T>() << ") uniform "
456			   << ImageTypePrefix<T>() << "image1DArray g_image_1d_array;" NL "layout(binding = 3, rgba32"
457			   << ImageFormatPostfix<T>() << ") uniform " << ImageTypePrefix<T>()
458			   << "image2DMS g_image_2dms;" NL "layout(binding = 4, rgba32" << ImageFormatPostfix<T>() << ") uniform "
459			   << ImageTypePrefix<T>() << "image2DMSArray g_image_2dms_array;";
460		}
461		if (subroutine)
462		{
463			os << NL "subroutine void FuncType(int coord);" NL "subroutine uniform FuncType g_func;";
464		}
465		if (stage == 0)
466		{ // VS
467			os << NL "void main() {" NL "  int coord = gl_VertexID;";
468		}
469		else if (stage == 1)
470		{ // TCS
471			os << NL "layout(vertices = 1) out;" NL "void main() {" NL "  gl_TessLevelInner[0] = 1;" NL
472					 "  gl_TessLevelInner[1] = 1;" NL "  gl_TessLevelOuter[0] = 1;" NL "  gl_TessLevelOuter[1] = 1;" NL
473					 "  gl_TessLevelOuter[2] = 1;" NL "  gl_TessLevelOuter[3] = 1;" NL "  int coord = gl_PrimitiveID;";
474		}
475		else if (stage == 2)
476		{ // TES
477			os << NL "layout(quads, point_mode) in;" NL "void main() {" NL "  int coord = gl_PrimitiveID;";
478		}
479		else if (stage == 3)
480		{ // GS
481			os << NL "layout(points) in;" NL "layout(points, max_vertices = 1) out;" NL "void main() {" NL
482					 "  int coord = gl_PrimitiveIDIn;";
483		}
484		else if (stage == 4)
485		{ // CS
486			os << NL "layout(local_size_x = 1) in;" NL "void main() {" NL "  int coord = int(gl_GlobalInvocationID.x);";
487		}
488		else if (stage == 5)
489		{ // FS
490			os << NL "void main() {" NL "  int coord = gl_PrimitiveID;";
491		}
492		if (subroutine)
493		{
494			os << NL "  g_func(coord);" NL "}" NL "subroutine(FuncType) void Func0(int coord) {";
495		}
496		if (ms_and_1d == false)
497		{
498			os << NL "  imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_2d), 0, 0));" NL
499					 "  imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_3d), 0));" NL
500					 "  imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_cube), 0, 0));" NL
501					 "  imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_cube_array), 0));" NL
502					 "  imageStore(g_result, ivec2(coord, 4), ivec4(imageSize(g_image_rect), 0, 0));" NL
503					 "  imageStore(g_result, ivec2(coord, 5), ivec4(imageSize(g_image_2d_array), 0));" NL
504					 "  imageStore(g_result, ivec2(coord, 6), ivec4(imageSize(g_image_buffer), 0, 0, 0));" NL "}";
505		}
506		else
507		{
508			os << NL "  imageStore(g_result, ivec2(coord, 0), ivec4(imageSize(g_image_1d), 0, 0, 0));" NL
509					 "  imageStore(g_result, ivec2(coord, 1), ivec4(imageSize(g_image_1d_array), 0, 0));" NL
510					 "  imageStore(g_result, ivec2(coord, 2), ivec4(imageSize(g_image_2dms), 0, 0));" NL
511					 "  imageStore(g_result, ivec2(coord, 3), ivec4(imageSize(g_image_2dms_array), 0));" NL
512					 "  imageStore(g_result, ivec2(coord, 4), ivec4(0));" NL
513					 "  imageStore(g_result, ivec2(coord, 5), ivec4(0));" NL
514					 "  imageStore(g_result, ivec2(coord, 6), ivec4(0));" NL "}";
515		}
516		return os.str();
517	}
518
519	bool CheckProgram(GLuint program)
520	{
521		if (program == 0)
522			return true;
523		GLint status;
524		glGetProgramiv(program, GL_LINK_STATUS, &status);
525
526		if (status == GL_FALSE)
527		{
528			GLint attached_shaders;
529			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
530
531			if (attached_shaders > 0)
532			{
533				std::vector<GLuint> shaders(attached_shaders);
534				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
535
536				for (GLint i = 0; i < attached_shaders; ++i)
537				{
538					GLenum type;
539					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
540					switch (type)
541					{
542					case GL_VERTEX_SHADER:
543						m_context.getTestContext().getLog()
544							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
545						break;
546					case GL_TESS_CONTROL_SHADER:
547						m_context.getTestContext().getLog()
548							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
549							<< tcu::TestLog::EndMessage;
550						break;
551					case GL_TESS_EVALUATION_SHADER:
552						m_context.getTestContext().getLog()
553							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
554							<< tcu::TestLog::EndMessage;
555						break;
556					case GL_GEOMETRY_SHADER:
557						m_context.getTestContext().getLog()
558							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
559						break;
560					case GL_FRAGMENT_SHADER:
561						m_context.getTestContext().getLog()
562							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
563						break;
564					case GL_COMPUTE_SHADER:
565						m_context.getTestContext().getLog()
566							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
567						break;
568					default:
569						m_context.getTestContext().getLog()
570							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
571						break;
572					}
573					GLint length;
574					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
575					if (length > 0)
576					{
577						std::vector<GLchar> source(length);
578						glGetShaderSource(shaders[i], length, NULL, &source[0]);
579						m_context.getTestContext().getLog()
580							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
581					}
582					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
583					if (length > 0)
584					{
585						std::vector<GLchar> log(length);
586						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
587						m_context.getTestContext().getLog()
588							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
589					}
590				}
591			}
592			GLint length;
593			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
594			if (length > 0)
595			{
596				std::vector<GLchar> log(length);
597				glGetProgramInfoLog(program, length, NULL, &log[0]);
598				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
599			}
600		}
601		return status == GL_TRUE ? true : false;
602	}
603
604public:
605	ImageSizeMachine()
606	{
607		glGenProgramPipelines(1, &m_pipeline);
608		memset(m_program, 0, sizeof(m_program));
609		glGenVertexArrays(1, &m_vertex_array);
610		glGenTextures(1, &m_texture);
611	}
612
613	~ImageSizeMachine()
614	{
615		glDeleteProgramPipelines(1, &m_pipeline);
616		for (int i = 0; i < 3; ++i)
617			glDeleteProgram(m_program[i]);
618		glDeleteVertexArrays(1, &m_vertex_array);
619		glDeleteTextures(1, &m_texture);
620	}
621
622	template <typename T>
623	long Run(int stage, bool ms_and_1d, ivec4 expected_result[7], bool subroutine = false)
624	{
625		if (stage == 0)
626		{ // VS
627			std::string		  vs	  = GenShader<T>(stage, ms_and_1d, subroutine);
628			const char* const glsl_vs = vs.c_str();
629			m_program[0]			  = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
630			glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
631		}
632		else if (stage == 1)
633		{ // TCS
634			const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
635										"void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
636			const char* const glsl_tes = "#version 430 core" NL "layout(quads, point_mode) in;" NL "void main() {}";
637			std::string		  tcs	  = GenShader<T>(stage, ms_and_1d, subroutine);
638			const char* const glsl_tcs = tcs.c_str();
639			m_program[0]			   = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
640			m_program[1]			   = glCreateShaderProgramv(GL_TESS_CONTROL_SHADER, 1, &glsl_tcs);
641			m_program[2]			   = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes);
642			glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
643			glUseProgramStages(m_pipeline, GL_TESS_CONTROL_SHADER_BIT, m_program[1]);
644			glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[2]);
645		}
646		else if (stage == 2)
647		{ // TES
648			const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
649										"void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
650			std::string		  tes	  = GenShader<T>(stage, ms_and_1d, subroutine);
651			const char* const glsl_tes = tes.c_str();
652			m_program[0]			   = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
653			m_program[1]			   = glCreateShaderProgramv(GL_TESS_EVALUATION_SHADER, 1, &glsl_tes);
654			glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
655			glUseProgramStages(m_pipeline, GL_TESS_EVALUATION_SHADER_BIT, m_program[1]);
656		}
657		else if (stage == 3)
658		{ // GS
659			const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
660										"void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
661			std::string		  gs	  = GenShader<T>(stage, ms_and_1d, subroutine);
662			const char* const glsl_gs = gs.c_str();
663			m_program[0]			  = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
664			m_program[1]			  = glCreateShaderProgramv(GL_GEOMETRY_SHADER, 1, &glsl_gs);
665			glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
666			glUseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, m_program[1]);
667		}
668		else if (stage == 4)
669		{ // CS
670			std::string		  cs	  = GenShader<T>(stage, ms_and_1d, subroutine);
671			const char* const glsl_cs = cs.c_str();
672			m_program[0]			  = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
673			glUseProgramStages(m_pipeline, GL_COMPUTE_SHADER_BIT, m_program[0]);
674		}
675		else if (stage == 5)
676		{ // FS
677			const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
678										"void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
679			std::string		  fs	  = GenShader<T>(stage, ms_and_1d, subroutine);
680			const char* const glsl_fs = fs.c_str();
681			m_program[0]			  = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
682			m_program[1]			  = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
683			glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
684			glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
685		}
686		for (int i = 0; i < 3; ++i)
687		{
688			if (!CheckProgram(m_program[i]))
689				return ERROR;
690		}
691
692		glBindTexture(GL_TEXTURE_2D, m_texture);
693		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
694		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
695		{
696			ivec4 data[7];
697			for (int i  = 0; i < 7; ++i)
698				data[i] = ivec4(100000);
699			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32I, 1, 7, 0, GL_RGBA_INTEGER, GL_INT, &data[0]);
700		}
701		glBindTexture(GL_TEXTURE_2D, 0);
702
703		glBindImageTexture(0, m_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32I);
704		glBindProgramPipeline(m_pipeline);
705		glBindVertexArray(m_vertex_array);
706		if (stage != 5)
707		{
708			glEnable(GL_RASTERIZER_DISCARD);
709		}
710		if (stage == 1 || stage == 2)
711		{ // TCS or TES
712			glPatchParameteri(GL_PATCH_VERTICES, 1);
713			glDrawArrays(GL_PATCHES, 0, 1);
714			glPatchParameteri(GL_PATCH_VERTICES, 3);
715		}
716		else if (stage == 4)
717		{ // CS
718			glDispatchCompute(1, 1, 1);
719		}
720		else
721		{
722			glDrawArrays(GL_POINTS, 0, 1);
723		}
724		glDisable(GL_RASTERIZER_DISCARD);
725
726		glBindTexture(GL_TEXTURE_2D, m_texture);
727		glMemoryBarrier(GL_TEXTURE_UPDATE_BARRIER_BIT);
728		{
729			ivec4 data[7];
730			glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_INT, &data[0]);
731			for (int i = 0; i < 7; ++i)
732			{
733				if (data[i] != expected_result[i])
734				{
735					m_context.getTestContext().getLog()
736						<< tcu::TestLog::Message << "Returned value is: (" << data[i][0] << " " << data[i][1] << " "
737						<< data[i][2] << " " << data[i][3] << "). Expected value is: (" << expected_result[i][0] << " "
738						<< expected_result[i][1] << " " << expected_result[i][2] << " " << expected_result[i][3]
739						<< "). Image unit is: " << (i + 1) << tcu::TestLog::EndMessage;
740					return ERROR;
741				}
742			}
743		}
744		return NO_ERROR;
745	}
746};
747//=============================================================================
748// 1.1.x.y BasicNonMS
749//-----------------------------------------------------------------------------
750
751template <typename T, int STAGE>
752class BasicNonMS : public ShaderImageSizeBase
753{
754	GLuint m_texture[7];
755	GLuint m_buffer;
756
757	virtual long Setup()
758	{
759		glGenTextures(7, m_texture);
760		glGenBuffers(1, &m_buffer);
761		return NO_ERROR;
762	}
763
764	virtual long Run()
765	{
766		if (!SupportedInStage(STAGE, 8))
767			return NOT_SUPPORTED;
768
769		const GLenum target[7] = { GL_TEXTURE_2D,		 GL_TEXTURE_3D,
770								   GL_TEXTURE_CUBE_MAP,  GL_TEXTURE_CUBE_MAP_ARRAY,
771								   GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY,
772								   GL_TEXTURE_BUFFER };
773		for (int i = 0; i < 7; ++i)
774		{
775			glBindTexture(target[i], m_texture[i]);
776			if (target[i] != GL_TEXTURE_BUFFER)
777			{
778				glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
779				glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
780			}
781
782			if (i == 0)
783			{
784				glTexStorage2D(target[i], 10, TexInternalFormat<T>(), 512, 128);
785				glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
786			}
787			else if (i == 1)
788			{
789				glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 8, 8, 4);
790				glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
791			}
792			else if (i == 2)
793			{
794				glTexStorage2D(target[i], 4, TexInternalFormat<T>(), 16, 16);
795				glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
796			}
797			else if (i == 3)
798			{
799				glTexStorage3D(target[i], 2, TexInternalFormat<T>(), 4, 4, 12);
800				glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
801			}
802			else if (i == 4)
803			{
804				glTexStorage2D(target[i], 1, TexInternalFormat<T>(), 16, 8);
805				glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
806			}
807			else if (i == 5)
808			{
809				glTexStorage3D(target[i], 3, TexInternalFormat<T>(), 127, 39, 12);
810				glBindImageTexture(6, m_texture[i], 2, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
811			}
812			else if (i == 6)
813			{
814				std::vector<GLubyte> data(256);
815				glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
816				glBufferData(GL_TEXTURE_BUFFER, 256, &data[0], GL_STATIC_DRAW);
817				glTexBuffer(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer);
818				glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
819			}
820		}
821		ImageSizeMachine machine;
822		ivec4			 res[7] = { ivec4(256, 64, 0, 0), ivec4(8, 8, 4, 0),   ivec4(16, 16, 0, 0), ivec4(2, 2, 2, 0),
823						 ivec4(16, 8, 0, 0),   ivec4(31, 9, 12, 0), ivec4(16, 0, 0, 0) };
824		return machine.Run<T>(STAGE, false, res);
825	}
826
827	virtual long Cleanup()
828	{
829		glDeleteTextures(7, m_texture);
830		glDeleteBuffers(1, &m_buffer);
831		return NO_ERROR;
832	}
833};
834//=============================================================================
835// 1.2.x.y BasicMS
836//-----------------------------------------------------------------------------
837
838template <typename T, int STAGE>
839class BasicMS : public ShaderImageSizeBase
840{
841	GLuint m_texture[4];
842
843	virtual long Setup()
844	{
845		glGenTextures(4, m_texture);
846		return NO_ERROR;
847	}
848
849	virtual long Run()
850	{
851		if (!SupportedInStage(STAGE, 5))
852			return NOT_SUPPORTED;
853		if (!SupportedSamples(4))
854			return NOT_SUPPORTED;
855
856		const GLenum target[4] = { GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE,
857								   GL_TEXTURE_2D_MULTISAMPLE_ARRAY };
858		for (int i = 0; i < 4; ++i)
859		{
860			glBindTexture(target[i], m_texture[i]);
861			if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY)
862			{
863				glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
864				glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
865			}
866
867			if (i == 0)
868			{
869				glTexStorage1D(target[i], 10, TexInternalFormat<T>(), 512);
870				glBindImageTexture(1, m_texture[i], 6, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
871			}
872			else if (i == 1)
873			{
874				glTexStorage2D(target[i], 3, TexInternalFormat<T>(), 15, 7);
875				glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
876			}
877			else if (i == 2)
878			{
879				glTexImage2DMultisample(target[i], 4, TexInternalFormat<T>(), 17, 19, GL_FALSE);
880				glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
881			}
882			else if (i == 3)
883			{
884				glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE);
885				glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
886			}
887		}
888		ImageSizeMachine machine;
889		ivec4 res[7] = { ivec4(8, 0, 0, 0), ivec4(7, 7, 0, 0), ivec4(17, 19, 0, 0), ivec4(64, 32, 5, 0), ivec4(0),
890						 ivec4(0),			ivec4(0) };
891		return machine.Run<T>(STAGE, true, res);
892	}
893
894	virtual long Cleanup()
895	{
896		glDeleteTextures(4, m_texture);
897		return NO_ERROR;
898	}
899};
900//=============================================================================
901// 2.1 AdvancedChangeSize
902//-----------------------------------------------------------------------------
903class AdvancedChangeSize : public ShaderImageSizeBase
904{
905	GLuint m_pipeline;
906	GLuint m_program[2];
907	GLuint m_vertex_array;
908	GLuint m_texture[2];
909
910	virtual long Setup()
911	{
912		glGenProgramPipelines(1, &m_pipeline);
913		memset(m_program, 0, sizeof(m_program));
914		glGenVertexArrays(1, &m_vertex_array);
915		glGenTextures(2, m_texture);
916		return NO_ERROR;
917	}
918
919	virtual long Run()
920	{
921		const char* const glsl_vs = "#version 430 core" NL "out gl_PerVertex { vec4 gl_Position; };" NL
922									"const vec2 g_position[3] = { vec2(-1, -1), vec2(3, -1), vec2(-1, 3) };" NL
923									"void main() { gl_Position = vec4(g_position[gl_VertexID], 0, 1); }";
924		const char* const glsl_fs =
925			"#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL
926			"layout(binding = 0, rgba8) uniform image2D g_image[2];" NL "uniform ivec2 g_expected_size[2];" NL
927			"uniform int g_0 = 0, g_1 = 1;" NL "void main() {" NL "  vec4 c = vec4(0, 1, 0, 1);" NL
928			"  if (imageSize(g_image[g_0]).xy != g_expected_size[g_0]) c = vec4(1, 0, 0, 1);" NL
929			"  if (imageSize(g_image[g_1]).yx != g_expected_size[g_1]) c = vec4(1, 0, 0, 1);" NL "  g_color = c;" NL
930			"}";
931		m_program[0] = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
932		m_program[1] = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
933		for (int i = 0; i < 2; ++i)
934			if (!CheckProgram(m_program[i]))
935				return ERROR;
936
937		glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, m_program[0]);
938		glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, m_program[1]);
939
940		glBindVertexArray(m_vertex_array);
941		glBindProgramPipeline(m_pipeline);
942
943		int size[2] = { 32, 128 };
944		for (int i = 0; i < 2; ++i)
945		{
946			glBindTexture(GL_TEXTURE_2D, m_texture[i]);
947			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
948			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
949			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[i], size[i], 0, GL_RGBA, GL_FLOAT, NULL);
950			glBindImageTexture(i, m_texture[i], 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
951		}
952
953		for (int i = 0; i < 3; ++i)
954		{
955			glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[0]"), size[0],
956							   size[0]);
957			glProgramUniform2i(m_program[1], glGetUniformLocation(m_program[1], "g_expected_size[1]"), size[1],
958							   size[1]);
959			glClear(GL_COLOR_BUFFER_BIT);
960			glDrawArrays(GL_TRIANGLES, 0, 3);
961
962			{
963				bool			  status = true;
964				std::vector<vec3> fb(getWindowWidth() * getWindowHeight());
965				glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGB, GL_FLOAT, &fb[0][0]);
966				if (!ValidateReadBuffer(0, 0, getWindowWidth(), getWindowHeight(), vec4(0, 1, 0, 1)))
967					status = false;
968				if (!status)
969					return ERROR;
970			}
971
972			size[0] /= 2;
973			size[1] /= 2;
974
975			glBindTexture(GL_TEXTURE_2D, m_texture[0]);
976			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[0], size[0], 0, GL_RGBA, GL_FLOAT, NULL);
977			glBindTexture(GL_TEXTURE_2D, m_texture[1]);
978			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size[1], size[1], 0, GL_RGBA, GL_FLOAT, NULL);
979		}
980		return NO_ERROR;
981	}
982
983	virtual long Cleanup()
984	{
985		glDeleteProgramPipelines(1, &m_pipeline);
986		for (int i = 0; i < 2; ++i)
987			glDeleteProgram(m_program[i]);
988		glDeleteVertexArrays(1, &m_vertex_array);
989		glDeleteTextures(2, m_texture);
990		return NO_ERROR;
991	}
992};
993//=============================================================================
994// 2.2.x.y AdvancedNonMS
995//-----------------------------------------------------------------------------
996
997template <typename T, int STAGE>
998class AdvancedNonMS : public ShaderImageSizeBase
999{
1000	GLuint m_texture[7];
1001	GLuint m_buffer;
1002
1003	virtual long Setup()
1004	{
1005		glGenTextures(7, m_texture);
1006		glGenBuffers(1, &m_buffer);
1007		return NO_ERROR;
1008	}
1009
1010	virtual long Run()
1011	{
1012		if (!SupportedInStage(STAGE, 8))
1013			return NOT_SUPPORTED;
1014
1015		const GLenum target[7] = { GL_TEXTURE_2D_ARRAY,		  GL_TEXTURE_3D,		GL_TEXTURE_CUBE_MAP_ARRAY,
1016								   GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_RECTANGLE, GL_TEXTURE_2D_ARRAY,
1017								   GL_TEXTURE_BUFFER };
1018		for (int i = 0; i < 7; ++i)
1019		{
1020			glBindTexture(target[i], m_texture[i]);
1021			if (target[i] != GL_TEXTURE_BUFFER)
1022			{
1023				glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1024				glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1025			}
1026
1027			if (i == 0)
1028			{
1029				glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1030				glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1031				glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 3, GL_READ_ONLY, TexInternalFormat<T>());
1032			}
1033			else if (i == 1)
1034			{
1035				glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 2, 0, TexFormat<T>(), TexType<T>(), NULL);
1036				glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1037				glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1038				glBindImageTexture(2, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1039			}
1040			else if (i == 2)
1041			{
1042				glTexImage3D(target[i], 0, TexInternalFormat<T>(), 2, 2, 12, 0, TexFormat<T>(), TexType<T>(), NULL);
1043				glTexImage3D(target[i], 1, TexInternalFormat<T>(), 1, 1, 12, 0, TexFormat<T>(), TexType<T>(), NULL);
1044				glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>());
1045			}
1046			else if (i == 3)
1047			{
1048				glTexImage3D(target[i], 0, TexInternalFormat<T>(), 4, 4, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1049				glTexImage3D(target[i], 1, TexInternalFormat<T>(), 2, 2, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1050				glTexImage3D(target[i], 2, TexInternalFormat<T>(), 1, 1, 18, 0, TexFormat<T>(), TexType<T>(), NULL);
1051				glBindImageTexture(4, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1052			}
1053			else if (i == 4)
1054			{
1055				glTexImage2D(target[i], 0, TexInternalFormat<T>(), 123, 11, 0, TexFormat<T>(), TexType<T>(), NULL);
1056				glBindImageTexture(5, m_texture[i], 0, GL_FALSE, 0, GL_READ_WRITE, TexInternalFormat<T>());
1057			}
1058			else if (i == 5)
1059			{
1060				glTexImage3D(target[i], 0, TexInternalFormat<T>(), 13, 7, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1061				glTexImage3D(target[i], 1, TexInternalFormat<T>(), 6, 3, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1062				glTexImage3D(target[i], 2, TexInternalFormat<T>(), 3, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1063				glTexImage3D(target[i], 3, TexInternalFormat<T>(), 1, 1, 4, 0, TexFormat<T>(), TexType<T>(), NULL);
1064				glBindImageTexture(6, m_texture[i], 1, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1065			}
1066			else if (i == 6)
1067			{
1068				glBindBuffer(GL_TEXTURE_BUFFER, m_buffer);
1069				glBufferData(GL_TEXTURE_BUFFER, 1024, NULL, GL_STATIC_DRAW);
1070				glTexBufferRange(GL_TEXTURE_BUFFER, TexInternalFormat<T>(), m_buffer, 256, 512);
1071				glBindImageTexture(7, m_texture[i], 0, GL_FALSE, 0, GL_WRITE_ONLY, TexInternalFormat<T>());
1072			}
1073		}
1074		ImageSizeMachine machine;
1075		ivec4			 res[7] = { ivec4(1, 1, 0, 0),	ivec4(2, 2, 1, 0), ivec4(2, 2, 0, 0), ivec4(2, 2, 3, 0),
1076						 ivec4(123, 11, 0, 0), ivec4(6, 3, 4, 0), ivec4(32, 0, 0, 0) };
1077		return machine.Run<T>(STAGE, false, res, true);
1078	}
1079
1080	virtual long Cleanup()
1081	{
1082		glDeleteTextures(7, m_texture);
1083		glDeleteBuffers(1, &m_buffer);
1084		return NO_ERROR;
1085	}
1086};
1087//=============================================================================
1088// 2.3.x.y AdvancedMS
1089//-----------------------------------------------------------------------------
1090template <typename T, int STAGE>
1091class AdvancedMS : public ShaderImageSizeBase
1092{
1093	GLuint m_texture[4];
1094
1095	virtual long Setup()
1096	{
1097		glGenTextures(4, m_texture);
1098		return NO_ERROR;
1099	}
1100
1101	virtual long Run()
1102	{
1103		if (!SupportedInStage(STAGE, 5))
1104			return NOT_SUPPORTED;
1105		if (!SupportedSamples(4))
1106			return NOT_SUPPORTED;
1107
1108		const GLenum target[4] = { GL_TEXTURE_1D, GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
1109								   GL_TEXTURE_2D_MULTISAMPLE_ARRAY };
1110		for (int i = 0; i < 4; ++i)
1111		{
1112			glBindTexture(target[i], m_texture[i]);
1113			if (target[i] == GL_TEXTURE_1D || target[i] == GL_TEXTURE_1D_ARRAY)
1114			{
1115				glTexParameteri(target[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1116				glTexParameteri(target[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1117			}
1118
1119			if (i == 0)
1120			{
1121				glTexImage1D(target[i], 0, TexInternalFormat<T>(), 7, 0, TexFormat<T>(), TexType<T>(), NULL);
1122				glTexImage1D(target[i], 1, TexInternalFormat<T>(), 3, 0, TexFormat<T>(), TexType<T>(), NULL);
1123				glTexImage1D(target[i], 2, TexInternalFormat<T>(), 1, 0, TexFormat<T>(), TexType<T>(), NULL);
1124				glBindImageTexture(1, m_texture[i], 1, GL_FALSE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1125			}
1126			else if (i == 1)
1127			{
1128				glTexImage2D(target[i], 0, TexInternalFormat<T>(), 7, 15, 0, TexFormat<T>(), TexType<T>(), NULL);
1129				glBindImageTexture(2, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1130			}
1131			else if (i == 2)
1132			{
1133				glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 7, 9, 3, GL_FALSE);
1134				glBindImageTexture(3, m_texture[i], 0, GL_FALSE, 1, GL_READ_WRITE, TexInternalFormat<T>());
1135			}
1136			else if (i == 3)
1137			{
1138				glTexImage3DMultisample(target[i], 4, TexInternalFormat<T>(), 64, 32, 5, GL_FALSE);
1139				glBindImageTexture(4, m_texture[i], 0, GL_TRUE, 0, GL_READ_ONLY, TexInternalFormat<T>());
1140			}
1141		}
1142		ImageSizeMachine machine;
1143		ivec4			 res[7] = { ivec4(3, 0, 0, 0), ivec4(7, 15, 0, 0), ivec4(7, 9, 0, 0), ivec4(64, 32, 5, 0),
1144						 ivec4(0),			ivec4(0),			ivec4(0) };
1145		return machine.Run<T>(STAGE, true, res, true);
1146	}
1147
1148	virtual long Cleanup()
1149	{
1150		glDeleteTextures(4, m_texture);
1151		return NO_ERROR;
1152	}
1153};
1154//=============================================================================
1155// 4.1 NegativeCompileTime
1156//-----------------------------------------------------------------------------
1157class NegativeCompileTime : public ShaderImageSizeBase
1158{
1159	virtual long Run()
1160	{
1161		// '#extension GL_ARB_shader_image_size : require' is missing
1162		if (!Compile("#version 420 core" NL "layout(location = 0) out vec4 g_color;" NL
1163					 "layout(binding = 0, rg16f) uniform image2D g_image;" NL "uniform ivec2 g_expected_size;" NL
1164					 "void main() {" NL "  if (imageSize(g_image) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL
1165					 "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
1166			return ERROR;
1167		// imageSize(sampler)
1168		if (!Compile("#version 430 core" NL "layout(location = 0) out vec4 g_color;" NL
1169					 "layout(binding = 0) uniform sampler2D g_sampler;" NL "uniform ivec2 g_expected_size;" NL
1170					 "void main() {" NL "  if (imageSize(g_sampler) == g_expected_size) g_color = vec4(0, 1, 0, 1);" NL
1171					 "  else g_color = vec4(1, 0, 0, 1);" NL "}"))
1172			return ERROR;
1173		return NO_ERROR;
1174	}
1175
1176	bool Compile(const std::string& source)
1177	{
1178		const GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
1179
1180		const char* const src = source.c_str();
1181		glShaderSource(sh, 1, &src, NULL);
1182		glCompileShader(sh);
1183
1184		GLchar log[1024];
1185		glGetShaderInfoLog(sh, sizeof(log), NULL, log);
1186		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader Info Log:\n"
1187											<< log << tcu::TestLog::EndMessage;
1188
1189		GLint status;
1190		glGetShaderiv(sh, GL_COMPILE_STATUS, &status);
1191		glDeleteShader(sh);
1192
1193		if (status == GL_TRUE)
1194		{
1195			m_context.getTestContext().getLog()
1196				<< tcu::TestLog::Message << "Compilation should fail." << tcu::TestLog::EndMessage;
1197			return false;
1198		}
1199		return true;
1200	}
1201};
1202
1203} // anonymous namespace
1204
1205ShaderImageSizeTests::ShaderImageSizeTests(deqp::Context& context) : TestCaseGroup(context, "shader_image_size", "")
1206{
1207}
1208
1209ShaderImageSizeTests::~ShaderImageSizeTests(void)
1210{
1211}
1212
1213void ShaderImageSizeTests::init()
1214{
1215	using namespace deqp;
1216	addChild(new TestSubcase(m_context, "basic-nonMS-vs-float", TestSubcase::Create<BasicNonMS<vec4, 0> >));
1217	addChild(new TestSubcase(m_context, "basic-nonMS-vs-int", TestSubcase::Create<BasicNonMS<ivec4, 0> >));
1218	addChild(new TestSubcase(m_context, "basic-nonMS-vs-uint", TestSubcase::Create<BasicNonMS<uvec4, 0> >));
1219	addChild(new TestSubcase(m_context, "basic-nonMS-tcs-float", TestSubcase::Create<BasicNonMS<vec4, 1> >));
1220	addChild(new TestSubcase(m_context, "basic-nonMS-tcs-int", TestSubcase::Create<BasicNonMS<ivec4, 1> >));
1221	addChild(new TestSubcase(m_context, "basic-nonMS-tcs-uint", TestSubcase::Create<BasicNonMS<uvec4, 1> >));
1222	addChild(new TestSubcase(m_context, "basic-nonMS-tes-float", TestSubcase::Create<BasicNonMS<vec4, 2> >));
1223	addChild(new TestSubcase(m_context, "basic-nonMS-tes-int", TestSubcase::Create<BasicNonMS<ivec4, 2> >));
1224	addChild(new TestSubcase(m_context, "basic-nonMS-tes-uint", TestSubcase::Create<BasicNonMS<uvec4, 2> >));
1225	addChild(new TestSubcase(m_context, "basic-nonMS-gs-float", TestSubcase::Create<BasicNonMS<vec4, 3> >));
1226	addChild(new TestSubcase(m_context, "basic-nonMS-gs-int", TestSubcase::Create<BasicNonMS<ivec4, 3> >));
1227	addChild(new TestSubcase(m_context, "basic-nonMS-gs-uint", TestSubcase::Create<BasicNonMS<uvec4, 3> >));
1228	addChild(new TestSubcase(m_context, "basic-nonMS-fs-float", TestSubcase::Create<BasicNonMS<vec4, 5> >));
1229	addChild(new TestSubcase(m_context, "basic-nonMS-fs-int", TestSubcase::Create<BasicNonMS<ivec4, 5> >));
1230	addChild(new TestSubcase(m_context, "basic-nonMS-fs-uint", TestSubcase::Create<BasicNonMS<uvec4, 5> >));
1231	addChild(new TestSubcase(m_context, "basic-nonMS-cs-float", TestSubcase::Create<BasicNonMS<vec4, 4> >));
1232	addChild(new TestSubcase(m_context, "basic-nonMS-cs-int", TestSubcase::Create<BasicNonMS<ivec4, 4> >));
1233	addChild(new TestSubcase(m_context, "basic-nonMS-cs-uint", TestSubcase::Create<BasicNonMS<uvec4, 4> >));
1234	addChild(new TestSubcase(m_context, "basic-ms-vs-float", TestSubcase::Create<BasicMS<vec4, 0> >));
1235	addChild(new TestSubcase(m_context, "basic-ms-vs-int", TestSubcase::Create<BasicMS<ivec4, 0> >));
1236	addChild(new TestSubcase(m_context, "basic-ms-vs-uint", TestSubcase::Create<BasicMS<uvec4, 0> >));
1237	addChild(new TestSubcase(m_context, "basic-ms-tcs-float", TestSubcase::Create<BasicMS<vec4, 1> >));
1238	addChild(new TestSubcase(m_context, "basic-ms-tcs-int", TestSubcase::Create<BasicMS<ivec4, 1> >));
1239	addChild(new TestSubcase(m_context, "basic-ms-tcs-uint", TestSubcase::Create<BasicMS<uvec4, 1> >));
1240	addChild(new TestSubcase(m_context, "basic-ms-tes-float", TestSubcase::Create<BasicMS<vec4, 2> >));
1241	addChild(new TestSubcase(m_context, "basic-ms-tes-int", TestSubcase::Create<BasicMS<ivec4, 2> >));
1242	addChild(new TestSubcase(m_context, "basic-ms-tes-uint", TestSubcase::Create<BasicMS<uvec4, 2> >));
1243	addChild(new TestSubcase(m_context, "basic-ms-gs-float", TestSubcase::Create<BasicMS<vec4, 3> >));
1244	addChild(new TestSubcase(m_context, "basic-ms-gs-int", TestSubcase::Create<BasicMS<ivec4, 3> >));
1245	addChild(new TestSubcase(m_context, "basic-ms-gs-uint", TestSubcase::Create<BasicMS<uvec4, 3> >));
1246	addChild(new TestSubcase(m_context, "basic-ms-fs-float", TestSubcase::Create<BasicMS<vec4, 5> >));
1247	addChild(new TestSubcase(m_context, "basic-ms-fs-int", TestSubcase::Create<BasicMS<ivec4, 5> >));
1248	addChild(new TestSubcase(m_context, "basic-ms-fs-uint", TestSubcase::Create<BasicMS<uvec4, 5> >));
1249	addChild(new TestSubcase(m_context, "basic-ms-cs-float", TestSubcase::Create<BasicMS<vec4, 4> >));
1250	addChild(new TestSubcase(m_context, "basic-ms-cs-int", TestSubcase::Create<BasicMS<ivec4, 4> >));
1251	addChild(new TestSubcase(m_context, "basic-ms-cs-uint", TestSubcase::Create<BasicMS<uvec4, 4> >));
1252	addChild(new TestSubcase(m_context, "advanced-changeSize", TestSubcase::Create<AdvancedChangeSize>));
1253	addChild(new TestSubcase(m_context, "advanced-nonMS-vs-float", TestSubcase::Create<AdvancedNonMS<vec4, 0> >));
1254	addChild(new TestSubcase(m_context, "advanced-nonMS-vs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 0> >));
1255	addChild(new TestSubcase(m_context, "advanced-nonMS-vs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 0> >));
1256	addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-float", TestSubcase::Create<AdvancedNonMS<vec4, 1> >));
1257	addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 1> >));
1258	addChild(new TestSubcase(m_context, "advanced-nonMS-tcs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 1> >));
1259	addChild(new TestSubcase(m_context, "advanced-nonMS-tes-float", TestSubcase::Create<AdvancedNonMS<vec4, 2> >));
1260	addChild(new TestSubcase(m_context, "advanced-nonMS-tes-int", TestSubcase::Create<AdvancedNonMS<ivec4, 2> >));
1261	addChild(new TestSubcase(m_context, "advanced-nonMS-tes-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 2> >));
1262	addChild(new TestSubcase(m_context, "advanced-nonMS-gs-float", TestSubcase::Create<AdvancedNonMS<vec4, 3> >));
1263	addChild(new TestSubcase(m_context, "advanced-nonMS-gs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 3> >));
1264	addChild(new TestSubcase(m_context, "advanced-nonMS-gs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 3> >));
1265	addChild(new TestSubcase(m_context, "advanced-nonMS-fs-float", TestSubcase::Create<AdvancedNonMS<vec4, 5> >));
1266	addChild(new TestSubcase(m_context, "advanced-nonMS-fs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 5> >));
1267	addChild(new TestSubcase(m_context, "advanced-nonMS-fs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 5> >));
1268	addChild(new TestSubcase(m_context, "advanced-nonMS-cs-float", TestSubcase::Create<AdvancedNonMS<vec4, 4> >));
1269	addChild(new TestSubcase(m_context, "advanced-nonMS-cs-int", TestSubcase::Create<AdvancedNonMS<ivec4, 4> >));
1270	addChild(new TestSubcase(m_context, "advanced-nonMS-cs-uint", TestSubcase::Create<AdvancedNonMS<uvec4, 4> >));
1271	addChild(new TestSubcase(m_context, "advanced-ms-vs-float", TestSubcase::Create<AdvancedMS<vec4, 0> >));
1272	addChild(new TestSubcase(m_context, "advanced-ms-vs-int", TestSubcase::Create<AdvancedMS<ivec4, 0> >));
1273	addChild(new TestSubcase(m_context, "advanced-ms-vs-uint", TestSubcase::Create<AdvancedMS<uvec4, 0> >));
1274	addChild(new TestSubcase(m_context, "advanced-ms-tcs-float", TestSubcase::Create<AdvancedMS<vec4, 1> >));
1275	addChild(new TestSubcase(m_context, "advanced-ms-tcs-int", TestSubcase::Create<AdvancedMS<ivec4, 1> >));
1276	addChild(new TestSubcase(m_context, "advanced-ms-tcs-uint", TestSubcase::Create<AdvancedMS<uvec4, 1> >));
1277	addChild(new TestSubcase(m_context, "advanced-ms-tes-float", TestSubcase::Create<AdvancedMS<vec4, 2> >));
1278	addChild(new TestSubcase(m_context, "advanced-ms-tes-int", TestSubcase::Create<AdvancedMS<ivec4, 2> >));
1279	addChild(new TestSubcase(m_context, "advanced-ms-tes-uint", TestSubcase::Create<AdvancedMS<uvec4, 2> >));
1280	addChild(new TestSubcase(m_context, "advanced-ms-gs-float", TestSubcase::Create<AdvancedMS<vec4, 3> >));
1281	addChild(new TestSubcase(m_context, "advanced-ms-gs-int", TestSubcase::Create<AdvancedMS<ivec4, 3> >));
1282	addChild(new TestSubcase(m_context, "advanced-ms-gs-uint", TestSubcase::Create<AdvancedMS<uvec4, 3> >));
1283	addChild(new TestSubcase(m_context, "advanced-ms-fs-float", TestSubcase::Create<AdvancedMS<vec4, 5> >));
1284	addChild(new TestSubcase(m_context, "advanced-ms-fs-int", TestSubcase::Create<AdvancedMS<ivec4, 5> >));
1285	addChild(new TestSubcase(m_context, "advanced-ms-fs-uint", TestSubcase::Create<AdvancedMS<uvec4, 5> >));
1286	addChild(new TestSubcase(m_context, "advanced-ms-cs-float", TestSubcase::Create<AdvancedMS<vec4, 4> >));
1287	addChild(new TestSubcase(m_context, "advanced-ms-cs-int", TestSubcase::Create<AdvancedMS<ivec4, 4> >));
1288	addChild(new TestSubcase(m_context, "advanced-ms-cs-uint", TestSubcase::Create<AdvancedMS<uvec4, 4> >));
1289	addChild(new TestSubcase(m_context, "negative-compileTime", TestSubcase::Create<NegativeCompileTime>));
1290}
1291
1292} // namespace gl4cts
1293