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 "es31cTextureGatherTests.hpp"
25#include "glwEnums.hpp"
26#include "glwFunctions.hpp"
27#include "tcuMatrix.hpp"
28#include "tcuMatrixUtil.hpp"
29#include "tcuRenderTarget.hpp"
30#include <cstdarg>
31#include <sstream>
32#include <string>
33#include <vector>
34
35namespace glcts
36{
37
38using namespace glw;
39using tcu::Vec4;
40using tcu::Vec3;
41using tcu::Vec2;
42using tcu::IVec4;
43using tcu::UVec4;
44
45namespace
46{
47
48class TGBase : public glcts::SubcaseBase
49{
50public:
51	virtual ~TGBase()
52	{
53	}
54
55	TGBase() : renderTarget(m_context.getRenderContext().getRenderTarget()), pixelFormat(renderTarget.getPixelFormat())
56	{
57	}
58
59	const tcu::RenderTarget& renderTarget;
60	const tcu::PixelFormat&  pixelFormat;
61
62	int GetWindowWidth()
63	{
64		return renderTarget.getWidth();
65	}
66
67	int GetWindowHeight()
68	{
69		return renderTarget.getHeight();
70	}
71
72	virtual std::string Title()
73	{
74		return "";
75	}
76
77	virtual std::string Purpose()
78	{
79		return "";
80	}
81
82	virtual std::string Method()
83	{
84		return "";
85	}
86
87	virtual std::string PassCriteria()
88	{
89		return "";
90	}
91
92	GLuint CreateProgram(const char* src_vs, const char* src_fs)
93	{
94		const GLuint p = glCreateProgram();
95		if (src_vs)
96		{
97			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
98			glAttachShader(p, sh);
99			glDeleteShader(sh);
100			glShaderSource(sh, 1, &src_vs, NULL);
101			glCompileShader(sh);
102		}
103		if (src_fs)
104		{
105			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
106			glAttachShader(p, sh);
107			glDeleteShader(sh);
108			glShaderSource(sh, 1, &src_fs, NULL);
109			glCompileShader(sh);
110		}
111		return p;
112	}
113
114	GLuint CreateComputeProgram(const std::string& cs)
115	{
116		const GLuint p = glCreateProgram();
117		if (!cs.empty())
118		{
119			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
120			glAttachShader(p, sh);
121			glDeleteShader(sh);
122			const char* const src[1] = { cs.c_str() };
123			glShaderSource(sh, 1, src, NULL);
124			glCompileShader(sh);
125		}
126		return p;
127	}
128
129	bool CheckProgram(GLuint program, bool* compile_error = NULL)
130	{
131		GLint compile_status = GL_TRUE;
132		GLint status;
133		glGetProgramiv(program, GL_LINK_STATUS, &status);
134
135		if (status == GL_FALSE)
136		{
137			GLint attached_shaders;
138			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
139
140			if (attached_shaders > 0)
141			{
142				std::vector<GLuint> shaders(attached_shaders);
143				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
144
145				for (GLint i = 0; i < attached_shaders; ++i)
146				{
147					GLenum type;
148					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
149					switch (type)
150					{
151					case GL_VERTEX_SHADER:
152						m_context.getTestContext().getLog()
153							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
154						break;
155					case GL_FRAGMENT_SHADER:
156						m_context.getTestContext().getLog()
157							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
158						break;
159					case GL_COMPUTE_SHADER:
160						m_context.getTestContext().getLog()
161							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
162						break;
163					default:
164						m_context.getTestContext().getLog()
165							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
166					}
167
168					GLint res;
169					glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
170					if (res != GL_TRUE)
171						compile_status = res;
172
173					GLint length;
174					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
175					if (length > 0)
176					{
177						std::vector<GLchar> source(length);
178						glGetShaderSource(shaders[i], length, NULL, &source[0]);
179						m_context.getTestContext().getLog()
180							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
181					}
182
183					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
184					if (length > 0)
185					{
186						std::vector<GLchar> log(length);
187						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
188						m_context.getTestContext().getLog()
189							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
190					}
191				}
192			}
193
194			GLint length;
195			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
196			if (length > 0)
197			{
198				std::vector<GLchar> log(length);
199				glGetProgramInfoLog(program, length, NULL, &log[0]);
200				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
201			}
202		}
203
204		if (compile_error)
205			*compile_error = (compile_status == GL_TRUE ? false : true);
206		if (compile_status != GL_TRUE)
207			return false;
208		return status == GL_TRUE ? true : false;
209	}
210
211	virtual long Setup()
212	{
213		return NO_ERROR;
214	}
215
216	virtual long Cleanup()
217	{
218		return NO_ERROR;
219	}
220};
221
222class GatherEnumsTest : public TGBase
223{
224	virtual std::string Title()
225	{
226		return "Basic Enum Test";
227	}
228
229	virtual std::string Purpose()
230	{
231		return "Verify that gather related enums are correct.";
232	}
233
234	virtual std::string Method()
235	{
236		return "Query GL_*_TEXTURE_GATHER_OFFSET enums.";
237	}
238
239	virtual std::string PassCriteria()
240	{
241		return "Values of enums meet GL spec requirements.";
242	}
243
244	virtual long Run()
245	{
246		GLint res;
247		glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
248		if (res > -8)
249		{
250			return ERROR;
251		}
252		glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
253		if (res < 7)
254		{
255			return ERROR;
256		}
257		return NO_ERROR;
258	}
259};
260
261class GatherGLSLCompile : public TGBase
262{
263	GLuint program;
264
265	virtual std::string Title()
266	{
267		return "GLSL Compile Test";
268	}
269
270	virtual std::string Purpose()
271	{
272		return "Verify that gather functions are visible in the shaders.";
273	}
274
275	virtual std::string Method()
276	{
277		return "Create shaders which use all types of gather functions.";
278	}
279
280	virtual std::string PassCriteria()
281	{
282		return "Programs compile and link successfuly.";
283	}
284
285	virtual std::string Uniforms()
286	{
287		return "uniform mediump sampler2D tex_2d;                  \n"
288			   "uniform mediump isamplerCube itex_cube;            \n"
289			   "uniform mediump usampler2DArray utex_2da;          \n"
290			   ""
291			   "uniform mediump sampler2DShadow tex_2ds;           \n"
292			   "uniform mediump samplerCubeShadow tex_cubes;       \n"
293			   "uniform mediump sampler2DArrayShadow tex_2das;     \n";
294	}
295
296	virtual std::string Sampling()
297	{
298		return "    textureGather(tex_2d,vec2(1));          \n"
299			   "    textureGather(itex_cube,vec3(1));       \n"
300			   "    textureGather(utex_2da,vec3(1));        \n"
301			   ""
302			   "    textureGather(tex_2ds,vec2(1), 0.5);    \n"
303			   "    textureGather(tex_cubes,vec3(1), 0.5);  \n"
304			   "    textureGather(tex_2das,vec3(1), 0.5);   \n"
305			   ""
306			   "    textureGatherOffset(tex_2d,vec2(1), ivec2(0));          \n"
307			   "    textureGatherOffset(utex_2da,vec3(1), ivec2(0));        \n"
308			   ""
309			   "    textureGatherOffset(tex_2ds,vec2(1), 0.5, ivec2(0));    \n"
310			   "    textureGatherOffset(tex_2das,vec3(1), 0.5, ivec2(0));   \n";
311	}
312
313	virtual std::string VertexShader()
314	{
315		return "#version 310 es                               \n" + Uniforms() +
316			   "  void main() {                            \n" + Sampling() +
317			   "    gl_Position = vec4(1);                 \n"
318			   "  }                                        \n";
319	}
320
321	virtual std::string FragmentShader()
322	{
323		return "#version 310 es                            \n"
324			   "precision highp float;                     \n"
325			   "out mediump vec4 color;                    \n" +
326			   Uniforms() + "  void main() {                            \n" + Sampling() +
327			   "    color = vec4(1);                       \n"
328			   "  }                                        \n";
329	}
330
331	virtual long Run()
332	{
333		program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str());
334		glLinkProgram(program);
335		if (!CheckProgram(program))
336			return ERROR;
337		return NO_ERROR;
338	}
339
340	virtual long Cleanup()
341	{
342		glDeleteProgram(program);
343		return NO_ERROR;
344	}
345};
346
347class GatherBase : public TGBase
348{
349public:
350	GLuint tex, fbo, rbo, program, vao, vbo;
351
352	bool IsFloatingPointTexture(GLenum internal_format)
353	{
354		switch (internal_format)
355		{
356		case GL_R32F:
357		case GL_RG32F:
358		case GL_RGB32F:
359		case GL_RGBA32F:
360		case GL_DEPTH_COMPONENT32F:
361			return true;
362		}
363
364		return false;
365	}
366
367	virtual GLvoid CreateTexture2DRgb(bool base_level = false)
368	{
369		GLenum		internal_format = GL_RGB32F;
370		GLenum		format			= GL_RGB;
371		const GLint csize			= base_level ? 64 : 32;
372		GLint		size			= csize;
373		GLenum		target			= GL_TEXTURE_2D;
374		GLenum		tex_type		= GL_FLOAT;
375
376		glGenTextures(1, &tex);
377		glBindTexture(target, tex);
378		for (int i = 0; size > 0; ++i, size /= 2)
379		{
380			std::vector<Vec3> pixels(size * size, Vec3(1.0));
381			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
382		}
383
384		Vec3 data[4] = { Vec3(12. / 16, 13. / 16, 14. / 16), Vec3(8. / 16, 9. / 16, 10. / 16),
385						 Vec3(0. / 16, 1. / 16, 2. / 16), Vec3(4. / 16, 5. / 16, 6. / 16) };
386
387		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
388		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
389		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
390		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
391		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
392
393		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
394		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
395		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
396
397		if (IsFloatingPointTexture(internal_format))
398		{
399			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
400			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
401		}
402	}
403
404	virtual GLvoid CreateTexture2DRg(bool base_level = false)
405	{
406		GLenum		internal_format = GL_RG32F;
407		GLenum		format			= GL_RG;
408		const GLint csize			= base_level ? 64 : 32;
409		GLint		size			= csize;
410		GLenum		target			= GL_TEXTURE_2D;
411		GLenum		tex_type		= GL_FLOAT;
412
413		glGenTextures(1, &tex);
414		glBindTexture(target, tex);
415		for (int i = 0; size > 0; ++i, size /= 2)
416		{
417			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
418			std::vector<Vec2> pixels(size * size, Vec2(1.0));
419			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
420		}
421
422		Vec2 data[4] = { Vec2(12. / 16, 13. / 16), Vec2(8. / 16, 9. / 16), Vec2(0. / 16, 1. / 16),
423						 Vec2(4. / 16, 5. / 16) };
424
425		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
426		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
427		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
428		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
429		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
430
431		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
432		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
433		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
434
435		if (IsFloatingPointTexture(internal_format))
436		{
437			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
438			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
439		}
440	}
441
442	virtual GLvoid CreateTexture2DR(bool base_level = false)
443	{
444		GLenum		internal_format = GL_R32F;
445		GLenum		format			= GL_RED;
446		const GLint csize			= base_level ? 64 : 32;
447		GLint		size			= csize;
448		GLenum		target			= GL_TEXTURE_2D;
449		GLenum		tex_type		= GL_FLOAT;
450
451		glGenTextures(1, &tex);
452		glBindTexture(target, tex);
453		for (int i = 0; size > 0; ++i, size /= 2)
454		{
455			std::vector<GLfloat> pixels(size * size, 1.0);
456			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
457		}
458
459		GLfloat data[4] = { 12. / 16., 8. / 16., 0. / 16., 4. / 16. };
460
461		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
462		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
463		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
464		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
465		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
466
467		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
468		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
469		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
470
471		if (IsFloatingPointTexture(internal_format))
472		{
473			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
474			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
475		}
476	}
477
478	virtual GLvoid CreateTexture2DInt()
479	{
480		GLenum		internal_format = InternalFormat();
481		const GLint csize			= 32;
482		GLint		size			= csize;
483		GLenum		target			= GL_TEXTURE_2D;
484		GLenum		tex_type		= Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
485
486		glGenTextures(1, &tex);
487		glBindTexture(target, tex);
488		for (int i = 0; size > 0; ++i, size /= 2)
489		{
490			glTexImage2D(target, i, internal_format, size, size, 0, GL_RGBA_INTEGER, tex_type, 0);
491		}
492		std::vector<IVec4> pixels(csize * csize, IVec4(999));
493		glTexSubImage2D(target, 0, 0, 0, csize, csize, GL_RGBA_INTEGER, tex_type, &pixels[0]);
494
495		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
496
497		glTexSubImage2D(target, 0, 22, 25, 2, 2, GL_RGBA_INTEGER, tex_type, data);
498		glTexSubImage2D(target, 0, 16, 10, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
499		glTexSubImage2D(target, 0, 11, 2, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
500		glTexSubImage2D(target, 0, 24, 13, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
501		glTexSubImage2D(target, 0, 9, 14, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
502
503		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
504		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
505		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
506		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
507		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
508	}
509
510	virtual GLvoid CreateTexture2DArrayInt(int slices, int data_slice)
511	{
512		GLenum		internal_format = InternalFormat();
513		const GLint csize			= 32;
514		GLint		size			= csize;
515		GLenum		tex_type		= Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
516
517		glGenTextures(1, &tex);
518		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
519		for (int i = 0; size > 0; ++i, size /= 2)
520		{
521			glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, GL_RGBA_INTEGER, tex_type, 0);
522		}
523		std::vector<IVec4> pixels(csize * csize, IVec4(999));
524		for (int i = 0; i < slices; ++i)
525		{
526			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, csize, csize, 1, GL_RGBA_INTEGER, tex_type, &pixels[0]);
527		}
528
529		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
530
531		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, GL_RGBA_INTEGER, tex_type, data);
532		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
533		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
534		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
535		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
536
537		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
538		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
539		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
540		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
541		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
542	}
543
544	virtual GLvoid CreateTexture2DArray(int slices, int data_slice)
545	{
546		GLenum		internal_format = InternalFormat();
547		GLenum		format			= Format();
548		const GLint csize			= 32;
549		GLint		size			= csize;
550
551		glGenTextures(1, &tex);
552		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
553		for (int i = 0; size > 0; ++i, size /= 2)
554		{
555			std::vector<Vec4> pixels(size * size * slices, Vec4(1.0));
556			glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, format, GL_FLOAT, &pixels[0]);
557		}
558
559		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
560						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
561
562		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, format, GL_FLOAT, data);
563		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, format, GL_FLOAT, data + 0);
564		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, format, GL_FLOAT, data + 1);
565		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, format, GL_FLOAT, data + 2);
566		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, format, GL_FLOAT, data + 3);
567
568		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
569		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
570		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
571
572		if (IsFloatingPointTexture(internal_format))
573		{
574			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
575			glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
576		}
577	}
578
579	virtual GLvoid CreateTextureCubeInt()
580	{
581		GLenum		internal_format = InternalFormat();
582		const GLint csize			= 32;
583		GLint		size			= csize;
584		GLenum		tex_type		= Type().find('u') != std::string::npos ? GL_UNSIGNED_INT : GL_INT;
585
586		const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
587								  GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
588								  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
589
590		glGenTextures(1, &tex);
591		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
592		for (int i = 0; size > 0; ++i, size /= 2)
593		{
594			for (int j = 0; j < 6; ++j)
595			{
596				glTexImage2D(faces[j], i, internal_format, size, size, 0, GL_RGBA_INTEGER, tex_type, 0);
597			}
598		}
599		std::vector<IVec4> pixels(csize * csize, IVec4(999));
600		for (int j = 0; j < 6; ++j)
601		{
602			glTexSubImage2D(faces[j], 0, 0, 0, csize, csize, GL_RGBA_INTEGER, tex_type, &pixels[0]);
603		}
604
605		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
606
607		for (int j = 0; j < 6; ++j)
608		{
609			glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, GL_RGBA_INTEGER, tex_type, data);
610			glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, GL_RGBA_INTEGER, tex_type, data + 0);
611			glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, GL_RGBA_INTEGER, tex_type, data + 1);
612			glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, GL_RGBA_INTEGER, tex_type, data + 2);
613			glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, GL_RGBA_INTEGER, tex_type, data + 3);
614		}
615
616		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
617		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
618		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
619		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
620		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
621	}
622
623	virtual GLvoid CreateTextureCube()
624	{
625		GLenum		internal_format = InternalFormat();
626		GLenum		format			= Format();
627		const GLint csize			= 32;
628		GLint		size			= csize;
629
630		const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
631								  GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
632								  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
633
634		glGenTextures(1, &tex);
635		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
636		for (int i = 0; size > 0; ++i, size /= 2)
637		{
638			std::vector<Vec4> pixels(size * size, Vec4(1.0));
639			for (int j = 0; j < 6; ++j)
640			{
641				glTexImage2D(faces[j], i, internal_format, size, size, 0, format, GL_FLOAT, &pixels[0]);
642			}
643		}
644
645		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
646						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
647
648		Vec4  depthData(data[0][0], data[1][0], data[2][0], data[3][0]);
649		Vec4* packedData = (format == GL_DEPTH_COMPONENT) ? &depthData : data;
650
651		for (int j = 0; j < 6; ++j)
652		{
653			glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, format, GL_FLOAT, packedData);
654			glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, format, GL_FLOAT, data + 0);
655			glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, format, GL_FLOAT, data + 1);
656			glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, format, GL_FLOAT, data + 2);
657			glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, format, GL_FLOAT, data + 3);
658		}
659
660		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
661		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
662		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
663
664		if (IsFloatingPointTexture(internal_format))
665		{
666			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
667			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
668		}
669	}
670
671	virtual GLvoid CreateTextureSRGB()
672	{
673		GLenum		internal_format = InternalFormat();
674		GLenum		format			= Format();
675		const GLint csize			= 32;
676		GLint		size			= csize;
677		GLenum		target			= GL_TEXTURE_2D;
678		GLenum		tex_type		= GL_UNSIGNED_BYTE;
679
680		glGenTextures(1, &tex);
681		glBindTexture(target, tex);
682		for (int i = 0; size > 0; ++i, size /= 2)
683		{
684			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
685		}
686		std::vector<GLubyte> pixels(csize * csize * 4, 255);
687		glTexSubImage2D(target, 0, 0, 0, csize, csize, format, tex_type, &pixels[0]);
688
689		if (format != GL_DEPTH_COMPONENT)
690		{
691			glGenerateMipmap(target);
692		}
693
694		GLubyte data[16] = { 240, 13, 14, 15, 160, 9, 10, 11, 0, 1, 2, 3, 80, 5, 6, 7 };
695
696		glTexSubImage2D(target, 0, 22, 25, 2, 2, format, tex_type, data);
697		glTexSubImage2D(target, 0, 16, 10, 1, 1, format, tex_type, data + 0);
698		glTexSubImage2D(target, 0, 11, 2, 1, 1, format, tex_type, data + 4);
699		glTexSubImage2D(target, 0, 24, 13, 1, 1, format, tex_type, data + 8);
700		glTexSubImage2D(target, 0, 9, 14, 1, 1, format, tex_type, data + 12);
701
702		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
703		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
704		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
705	}
706
707	virtual GLvoid CreateTexture2D(bool base_level = false)
708	{
709		GLenum		internal_format = InternalFormat();
710		GLenum		format			= Format();
711		const GLint csize			= base_level ? 64 : 32;
712		GLint		size			= csize;
713		GLenum		target			= GL_TEXTURE_2D;
714		GLenum		tex_type		= InternalFormat() == GL_SRGB8_ALPHA8 ? GL_UNSIGNED_BYTE : GL_FLOAT;
715
716		glGenTextures(1, &tex);
717		glBindTexture(target, tex);
718		for (int i = 0; size > 0; ++i, size /= 2)
719		{
720			std::vector<Vec4> pixels(size * size, Vec4(1.0));
721			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, &pixels[0]);
722		}
723
724		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
725						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
726
727		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
728		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
729		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
730		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
731		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
732
733		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
734		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
735		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
736
737		if (IsFloatingPointTexture(internal_format))
738		{
739			glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
740			glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
741		}
742
743		if (base_level)
744			glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 1);
745	}
746
747	virtual std::string FallthroughVertexShader()
748	{
749		return "#version 310 es                       \n"
750			   "in vec4 v_in_0;                    \n"
751			   "flat out vec4 v_out_0;             \n"
752			   "void main() {                      \n"
753			   "    gl_Position = vec4(0,0,0,1);   \n"
754			   "#ifdef GL_ES                       \n"
755			   "    gl_PointSize = 1.0f;           \n"
756			   "#endif                             \n"
757			   "    v_out_0 = v_in_0;              \n"
758			   "}";
759	}
760
761	virtual std::string FallthroughFragmentShader()
762	{
763		return "#version 310 es                          \n"
764			   "precision highp float;                   \n"
765			   "out mediump vec4 f_out_0;                \n"
766			   "flat in  mediump vec4 v_out_0;           \n"
767			   "void main() {                            \n"
768			   "    f_out_0 = v_out_0;                   \n"
769			   "}";
770	}
771
772	virtual std::string TestFunction()
773	{
774		return Sampler() + TextBody();
775	}
776
777	virtual std::string Sampler()
778	{
779		return "uniform mediump sampler2D my_sampler;                  \n";
780	}
781
782	virtual std::string Type()
783	{
784		return "vec4";
785	}
786
787	virtual std::string TextBody()
788	{
789		std::string str_if = "    if (all(lessThanEqual(abs(tmp - " + Expected() + "), vec4(0.039)))) {           \n";
790		if (Type().find('u') != std::string::npos || Type().find('i') != std::string::npos)
791		{
792			str_if = "    if (tmp == " + Expected() + ") {           \n";
793		}
794		return "vec4 test_function(vec4 p) {                                                                         "
795			   "\n" +
796			   Offset() + "    mediump " + Type() + " tmp = " + Gather() +
797			   ";                                                   \n" + str_if +
798			   "        return vec4(0.0, 1.0, 0.0, 1.0);                                                             \n"
799			   "    } else {                                                                                         \n"
800			   "        return vec4(float(tmp.x), float(tmp.y), float(tmp.z), float(tmp.w));                         \n"
801			   "    }                                                                                                \n"
802			   "}\n";
803	}
804
805	virtual std::string Gather()
806	{
807		return "textureGather(my_sampler, vec2(p.x, p.y))";
808	}
809
810	virtual std::string Offset()
811	{
812		return "";
813	}
814
815	virtual std::string VertexShader()
816	{
817		return "#version 310 es                                       \n"
818			   ""
819			   "in mediump vec4 v_in_0;                            \n"
820			   "flat out mediump vec4 v_out_0;                     \n" +
821			   TestFunction() + "void main() {                                      \n"
822								"    gl_Position = vec4(0, 0, 0, 1);                \n"
823								"#ifdef GL_ES                                       \n"
824								"    gl_PointSize = 1.0f;                           \n"
825								"#endif                                             \n"
826								"    v_out_0 = test_function(v_in_0);               \n"
827								"}";
828	}
829
830	virtual std::string FragmentShader()
831	{
832		return "#version 310 es                                       \n"
833			   ""
834			   "precision highp float;                             \n"
835			   "flat in mediump vec4 v_out_0;                      \n"
836			   "out mediump vec4 f_out_0;                          \n" +
837			   TestFunction() + "void main() {                                      \n"
838								"    f_out_0 = test_function(v_out_0);              \n"
839								"}";
840	}
841
842	virtual std::string ComputeShader()
843	{
844		return "#version 310 es                                       \n"
845			   "layout(local_size_x = 1, local_size_y = 1) in;        \n"
846			   "layout(std430) buffer Output {                        \n"
847			   "  mediump vec4 data;                                  \n"
848			   "} g_out;                                              \n"
849			   "uniform mediump vec4 cs_in;                           \n" +
850			   TestFunction() + "void main() {                                         \n"
851								"  g_out.data = test_function(cs_in);                  \n"
852								"}                                                     \n";
853	}
854
855	virtual void Init()
856	{
857		CreateTexture2D();
858	}
859
860	virtual long Verify()
861	{
862		std::vector<GLubyte> data(4);
863		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
864		if (data[0] != 0 || data[1] != 255 || data[2] != 0 || data[3] != 255)
865		{
866			m_context.getTestContext().getLog()
867				<< tcu::TestLog::Message << "Expected Vec4(0, 255, 0, 255), got: " << data[0] << ", " << data[1] << ", "
868				<< data[2] << ", " << data[3] << tcu::TestLog::EndMessage;
869			return ERROR;
870		}
871		return NO_ERROR;
872	}
873
874	virtual std::string Expected()
875	{
876		return "vec4(0./16., 4./16., 8./16., 12./16.)";
877	}
878
879	virtual GLenum InternalFormat()
880	{
881		return GL_RGBA32F;
882	}
883
884	virtual GLenum Format()
885	{
886		return GL_RGBA;
887	}
888
889	virtual Vec4 BufferData()
890	{
891		return Vec4(23. / 32, 26. / 32, 5, 3);
892	}
893
894	virtual bool Supported()
895	{
896		return true;
897	}
898
899	virtual long Run()
900	{
901		if (!Supported())
902			return NO_ERROR;
903		Init();
904
905		glGenFramebuffers(1, &fbo);
906		glGenRenderbuffers(1, &rbo);
907		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
908		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 1);
909		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
910		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
911		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
912		glDrawBuffers(1, &drawBuffer);
913		GLfloat colorf[4] = { 0, 0, 0, 0 };
914		glClearBufferfv(GL_COLOR, 0, colorf);
915		glViewport(0, 0, 1, 1);
916
917		glGenVertexArrays(1, &vao);
918		glBindVertexArray(vao);
919		glGenBuffers(1, &vbo);
920		glBindBuffer(GL_ARRAY_BUFFER, vbo);
921		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
922		glEnableVertexAttribArray(0);
923		Vec4 buffData = BufferData();
924		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
925
926		for (int i = 0; i < 2; ++i)
927		{
928			if (i == 0)
929				program = CreateProgram(VertexShader().c_str(), FallthroughFragmentShader().c_str());
930			else
931				program = CreateProgram(FallthroughVertexShader().c_str(), FragmentShader().c_str());
932			glBindAttribLocation(program, 0, "v_in_0");
933			glLinkProgram(program);
934			if (!CheckProgram(program))
935				return ERROR;
936			glUseProgram(program);
937
938			glDrawArrays(GL_POINTS, 0, 1);
939			glReadBuffer(GL_COLOR_ATTACHMENT0);
940
941			glDeleteProgram(program);
942
943			if (Verify() == ERROR)
944				return ERROR;
945		}
946
947		return TestCompute();
948	}
949
950	virtual long TestCompute()
951	{
952		GLuint m_buffer;
953
954		program = CreateComputeProgram(ComputeShader());
955		glLinkProgram(program);
956		if (!CheckProgram(program))
957			return ERROR;
958		glUseProgram(program);
959
960		glUniform4f(glGetUniformLocation(program, "cs_in"), BufferData().x(), BufferData().y(), BufferData().z(),
961					BufferData().w());
962
963		glGenBuffers(1, &m_buffer);
964		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
965		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Vec4), NULL, GL_DYNAMIC_DRAW);
966		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
967
968		glDispatchCompute(1, 1, 1);
969
970		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
971		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
972		long error = VerifyCompute();
973		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
974		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
975		glDeleteBuffers(1, &m_buffer);
976
977		return error;
978	}
979
980	virtual long VerifyCompute()
981	{
982		Vec4* data;
983		data = static_cast<Vec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Vec4), GL_MAP_READ_BIT));
984		if (data[0] != Vec4(0, 1, 0, 1))
985		{
986			m_context.getTestContext().getLog()
987				<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data[0].x() << ", " << data[0].y()
988				<< ", " << data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
989			return ERROR;
990		}
991		return NO_ERROR;
992	}
993
994	virtual long Cleanup()
995	{
996		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
997		glDisableVertexAttribArray(0);
998		glDeleteTextures(1, &tex);
999		glDeleteVertexArrays(1, &vao);
1000		glDeleteBuffers(1, &vbo);
1001		glDeleteRenderbuffers(1, &rbo);
1002		glDeleteFramebuffers(1, &fbo);
1003		glDeleteProgram(program);
1004		return NO_ERROR;
1005	}
1006};
1007
1008class PlainGatherFloat2D : public GatherBase
1009{
1010};
1011
1012class PlainGatherInt2D : public GatherBase
1013{
1014public:
1015	virtual GLenum InternalFormat()
1016	{
1017		return GL_RGBA32I;
1018	}
1019
1020	virtual void Init()
1021	{
1022		CreateTexture2DInt();
1023	}
1024
1025	virtual std::string Expected()
1026	{
1027		return "ivec4(0, 4, 8, 12)";
1028	}
1029
1030	virtual std::string Sampler()
1031	{
1032		return "uniform mediump isampler2D my_sampler;  \n";
1033	}
1034
1035	virtual std::string Type()
1036	{
1037		return "ivec4";
1038	}
1039};
1040
1041class PlainGatherUint2D : public GatherBase
1042{
1043public:
1044	virtual GLenum InternalFormat()
1045	{
1046		return GL_RGBA32UI;
1047	}
1048
1049	virtual void Init()
1050	{
1051		CreateTexture2DInt();
1052	}
1053
1054	virtual std::string Expected()
1055	{
1056		return "uvec4(2u, 6u, 10u, 14u)";
1057	}
1058
1059	virtual std::string Sampler()
1060	{
1061		return "uniform  mediump usampler2D my_sampler;                     \n";
1062	}
1063
1064	virtual Vec4 BufferData()
1065	{
1066		return Vec4(22.9f / 32, 25.9f / 32, 2, 2);
1067	}
1068
1069	virtual std::string Type()
1070	{
1071		return "uvec4";
1072	}
1073
1074	virtual std::string Gather()
1075	{
1076		return "textureGather(my_sampler, vec2(p.x, p.y), 2)";
1077	}
1078};
1079
1080class PlainGatherDepth2D : public GatherBase
1081{
1082public:
1083	virtual GLenum InternalFormat()
1084	{
1085		return GL_DEPTH_COMPONENT32F;
1086	}
1087
1088	virtual GLenum Format()
1089	{
1090		return GL_DEPTH_COMPONENT;
1091	}
1092
1093	virtual void Init()
1094	{
1095		CreateTexture2D();
1096		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1097	}
1098
1099	virtual std::string Expected()
1100	{
1101		return "vec4(1.0, 1.0, 0.0, 0.0)";
1102	}
1103
1104	virtual Vec4 BufferData()
1105	{
1106		return Vec4(23. / 32, 26. / 32, 13.5 / 16, 3);
1107	}
1108
1109	virtual std::string Sampler()
1110	{
1111		return "uniform mediump sampler2DShadow my_sampler;                     \n";
1112	}
1113
1114	virtual std::string Gather()
1115	{
1116		return "textureGather(my_sampler, vec2(p.x, p.y), p.z)";
1117	}
1118};
1119
1120class PlainGatherFloat2DArray : public GatherBase
1121{
1122public:
1123	virtual void Init()
1124	{
1125		CreateTexture2DArray(9, 5);
1126	}
1127
1128	virtual std::string Sampler()
1129	{
1130		return "uniform mediump sampler2DArray my_sampler;                     \n";
1131	}
1132
1133	virtual std::string Gather()
1134	{
1135		return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
1136	}
1137};
1138
1139class PlainGatherInt2DArray : public GatherBase
1140{
1141public:
1142	virtual void Init()
1143	{
1144		CreateTexture2DArrayInt(20, 11);
1145	}
1146
1147	virtual GLenum InternalFormat()
1148	{
1149		return GL_RGBA32I;
1150	}
1151
1152	virtual std::string Expected()
1153	{
1154		return "ivec4(3, 7, 11, 15)";
1155	}
1156
1157	virtual std::string Type()
1158	{
1159		return "ivec4";
1160	}
1161
1162	virtual Vec4 BufferData()
1163	{
1164		return Vec4(23. / 32, 26. / 32, 11, 3);
1165	}
1166
1167	virtual std::string Sampler()
1168	{
1169		return "uniform mediump isampler2DArray my_sampler;                     \n";
1170	}
1171
1172	virtual std::string Gather()
1173	{
1174		return "textureGather(my_sampler, vec3(p.x, p.y, p.z), 3)";
1175	}
1176};
1177
1178class PlainGatherUint2DArray : public GatherBase
1179{
1180public:
1181	virtual void Init()
1182	{
1183		CreateTexture2DArrayInt(3, 1);
1184	}
1185
1186	virtual GLenum InternalFormat()
1187	{
1188		return GL_RGBA32UI;
1189	}
1190
1191	virtual std::string Expected()
1192	{
1193		return "uvec4(0u, 4u, 8u, 12u)";
1194	}
1195
1196	virtual std::string Type()
1197	{
1198		return "uvec4";
1199	}
1200
1201	virtual Vec4 BufferData()
1202	{
1203		return Vec4(23. / 32, 26. / 32, 1, 3);
1204	}
1205
1206	virtual std::string Sampler()
1207	{
1208		return "uniform  mediump usampler2DArray my_sampler;                     \n";
1209	}
1210
1211	virtual std::string Gather()
1212	{
1213		return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
1214	}
1215};
1216
1217class PlainGatherDepth2DArray : public GatherBase
1218{
1219public:
1220	virtual GLenum InternalFormat()
1221	{
1222		return GL_DEPTH_COMPONENT32F;
1223	}
1224
1225	virtual GLenum Format()
1226	{
1227		return GL_DEPTH_COMPONENT;
1228	}
1229
1230	virtual void Init()
1231	{
1232		CreateTexture2DArray(9, 5);
1233		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1234	}
1235
1236	virtual std::string Expected()
1237	{
1238		return "vec4(1.0, 1.0, 0.0, 0.0)";
1239	}
1240
1241	virtual Vec4 BufferData()
1242	{
1243		return Vec4(23. / 32, 26. / 32, 5, 13.5 / 16);
1244	}
1245
1246	virtual std::string Sampler()
1247	{
1248		return "uniform mediump sampler2DArrayShadow my_sampler;                     \n";
1249	}
1250
1251	virtual std::string Gather()
1252	{
1253		return "textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w)";
1254	}
1255};
1256
1257class PlainGatherFloatCube : public GatherBase
1258{
1259public:
1260	virtual void Init()
1261	{
1262		CreateTextureCube();
1263	}
1264
1265	virtual Vec4 BufferData()
1266	{
1267		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1268	}
1269
1270	virtual std::string Sampler()
1271	{
1272		return "uniform mediump samplerCube my_sampler;                     \n";
1273	}
1274
1275	virtual std::string Gather()
1276	{
1277		return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
1278	}
1279};
1280
1281class PlainGatherIntCube : public GatherBase
1282{
1283public:
1284	virtual void Init()
1285	{
1286		CreateTextureCubeInt();
1287	}
1288
1289	virtual Vec4 BufferData()
1290	{
1291		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1292	}
1293
1294	virtual std::string Sampler()
1295	{
1296		return "uniform mediump isamplerCube my_sampler;                     \n";
1297	}
1298
1299	virtual std::string Gather()
1300	{
1301		return "textureGather(my_sampler, vec3(p.x, p.y, p.z))";
1302	}
1303
1304	virtual GLenum InternalFormat()
1305	{
1306		return GL_RGBA32I;
1307	}
1308
1309	virtual std::string Expected()
1310	{
1311		return "ivec4(0, 4, 8, 12)";
1312	}
1313
1314	virtual std::string Type()
1315	{
1316		return "ivec4";
1317	}
1318};
1319
1320class PlainGatherUintCube : public GatherBase
1321{
1322public:
1323	virtual void Init()
1324	{
1325		CreateTextureCubeInt();
1326	}
1327
1328	virtual Vec4 BufferData()
1329	{
1330		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1331	}
1332
1333	virtual std::string Sampler()
1334	{
1335		return "uniform  mediump usamplerCube my_sampler;                     \n";
1336	}
1337
1338	virtual std::string Gather()
1339	{
1340		return "textureGather(my_sampler, vec3(p.x, p.y, p.z), 0)";
1341	}
1342
1343	virtual GLenum InternalFormat()
1344	{
1345		return GL_RGBA32UI;
1346	}
1347
1348	virtual std::string Expected()
1349	{
1350		return "uvec4(0u, 4u, 8u, 12u)";
1351	}
1352
1353	virtual std::string Type()
1354	{
1355		return "uvec4";
1356	}
1357};
1358
1359class PlainGatherDepthCube : public GatherBase
1360{
1361public:
1362	virtual void Init()
1363	{
1364		CreateTextureCube();
1365		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1366	}
1367
1368	virtual GLenum InternalFormat()
1369	{
1370		return GL_DEPTH_COMPONENT32F;
1371	}
1372
1373	virtual GLenum Format()
1374	{
1375		return GL_DEPTH_COMPONENT;
1376	}
1377
1378	virtual Vec4 BufferData()
1379	{
1380		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1381	}
1382
1383	virtual std::string Sampler()
1384	{
1385		return "uniform mediump samplerCubeShadow my_sampler;                     \n";
1386	}
1387
1388	virtual std::string Gather()
1389	{
1390		return "textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w)";
1391	}
1392
1393	virtual std::string Expected()
1394	{
1395		return "vec4(0.0, 0.0, 1.0, 1.0)";
1396	}
1397};
1398
1399class OffsetGatherFloat2D : public GatherBase
1400{
1401	virtual Vec4 BufferData()
1402	{
1403		return Vec4(19. / 32, 22. / 32, 4, 4);
1404	}
1405
1406	virtual std::string Offset()
1407	{
1408		return "const mediump ivec2 offset = ivec2(4);         \n";
1409	}
1410
1411	virtual std::string Gather()
1412	{
1413		return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset)";
1414	}
1415};
1416
1417class OffsetGatherInt2D : public PlainGatherInt2D
1418{
1419	virtual Vec4 BufferData()
1420	{
1421		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 4);
1422	}
1423
1424	virtual std::string Offset()
1425	{
1426		return "const mediump ivec2 offset = ivec2(4);         \n";
1427	}
1428
1429	virtual std::string Gather()
1430	{
1431		return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset)";
1432	}
1433};
1434
1435class OffsetGatherUint2D : public PlainGatherUint2D
1436{
1437	virtual Vec4 BufferData()
1438	{
1439		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 2);
1440	}
1441
1442	virtual std::string Offset()
1443	{
1444		return "const mediump ivec2 offset = ivec2(4);         \n";
1445	}
1446
1447	virtual std::string Gather()
1448	{
1449		return "textureGatherOffset(my_sampler, vec2(p.x, p.y), offset, 2)";
1450	}
1451};
1452
1453class OffsetGatherDepth2D : public PlainGatherDepth2D
1454{
1455	virtual Vec4 BufferData()
1456	{
1457		return Vec4(19. / 32, 22. / 32, 4, 13.5 / 16);
1458	}
1459
1460	virtual std::string Offset()
1461	{
1462		return "const mediump ivec2 offset = ivec2(4);         \n";
1463	}
1464
1465	virtual std::string Gather()
1466	{
1467		return "textureGatherOffset(my_sampler, vec2(p.x, p.y), p.w, offset)";
1468	}
1469};
1470
1471class OffsetGatherFloat2DArray : public PlainGatherFloat2DArray
1472{
1473	virtual Vec4 BufferData()
1474	{
1475		return Vec4(19. / 32, 22. / 32, 5, 4);
1476	}
1477
1478	virtual std::string Offset()
1479	{
1480		return "const mediump ivec2 offset = ivec2(4);         \n";
1481	}
1482
1483	virtual std::string Gather()
1484	{
1485		return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset)";
1486	}
1487};
1488
1489class OffsetGatherInt2DArray : public PlainGatherInt2DArray
1490{
1491	virtual Vec4 BufferData()
1492	{
1493		return Vec4(19. / 32, 22. / 32, 11, 4);
1494	}
1495
1496	virtual std::string Offset()
1497	{
1498		return "const mediump ivec2 offset = ivec2(4);         \n";
1499	}
1500
1501	virtual std::string Gather()
1502	{
1503		return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset, 3)";
1504	}
1505};
1506
1507class OffsetGatherUint2DArray : public PlainGatherUint2DArray
1508{
1509	virtual Vec4 BufferData()
1510	{
1511		return Vec4(19. / 32, 22. / 32, 1, 4);
1512	}
1513
1514	virtual std::string Offset()
1515	{
1516		return "const mediump ivec2 offset = ivec2(4);         \n";
1517	}
1518
1519	virtual std::string Gather()
1520	{
1521		return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), offset, 0)";
1522	}
1523};
1524
1525class OffsetGatherDepth2DArray : public PlainGatherDepth2DArray
1526{
1527	virtual void Init()
1528	{
1529		CreateTexture2DArray(7, 3);
1530		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1531	}
1532
1533	virtual Vec4 BufferData()
1534	{
1535		return Vec4(19. / 32, 22. / 32, 3, 4);
1536	}
1537
1538	virtual std::string Offset()
1539	{
1540		return "const mediump ivec2 offset = ivec2(4);         \n";
1541	}
1542
1543	virtual std::string Gather()
1544	{
1545		return "textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), p.y + (5.0/32.0), offset)";
1546	}
1547};
1548
1549class Swizzle : public PlainGatherFloat2D
1550{
1551	virtual std::string Gather()
1552	{
1553		return "textureGather(my_sampler, vec2(p.x, p.y), 1).yzww";
1554	}
1555
1556	virtual std::string Expected()
1557	{
1558		return "vec4(5./16., 9./16., 13./16., 13./16.)";
1559	}
1560};
1561
1562class BaseLevel : public PlainGatherFloat2D
1563{
1564	virtual void Init()
1565	{
1566		CreateTexture2D(true);
1567	}
1568};
1569
1570class IncompleteTexture : public PlainGatherFloat2D
1571{
1572	virtual void Init()
1573	{
1574		CreateTexture2D();
1575		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
1576	}
1577
1578	virtual std::string Expected()
1579	{
1580		return "vec4(0)";
1581	}
1582
1583	virtual std::string Gather()
1584	{
1585		return "textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(0), 1)";
1586	}
1587};
1588
1589class IncompleteTextureLastComp : public PlainGatherFloat2D
1590{
1591	virtual void Init()
1592	{
1593		CreateTexture2D();
1594		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
1595	}
1596
1597	virtual std::string Expected()
1598	{
1599		return "vec4(1.0)";
1600	}
1601
1602	virtual std::string Gather()
1603	{
1604		return "textureGather(my_sampler, vec2(p.x, p.y), 3)";
1605	}
1606};
1607
1608class TriangleDraw : public GatherBase
1609{
1610	GLuint program, rbo, fbo, vao, vbo;
1611
1612	virtual std::string VertexShader()
1613	{
1614		return "#version 310 es                               \n"
1615			   "flat out mediump vec2 texcoords;              \n"
1616			   "in mediump vec4 Vertex;                       \n"
1617			   "void main() {                                 \n"
1618			   "   gl_Position = Vertex;                      \n"
1619			   "   texcoords = (Vertex.xy + vec2(1.0)) / 2.0; \n"
1620			   "}\n";
1621	}
1622
1623	virtual std::string FragmentShader()
1624	{
1625		return "#version 310 es                                   \n"
1626			   "precision highp float;                            \n"
1627			   "flat in mediump vec2 texcoords;                   \n"
1628			   "out highp uvec4 FragColor;                        \n"
1629			   "uniform mediump sampler2D tex;                    \n"
1630			   "void main() {                                     \n"
1631			   "   vec4 data = textureGather(tex, texcoords, 2);  \n"
1632			   "   FragColor = floatBitsToUint(data);             \n"
1633			   "}\n";
1634	}
1635
1636	virtual long Run()
1637	{
1638		glGenFramebuffers(1, &fbo);
1639		glGenRenderbuffers(1, &rbo);
1640		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1641		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 100, 100);
1642		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1643		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1644		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
1645		glDrawBuffers(1, &drawBuffer);
1646		GLfloat colorf[4] = { 0, 0, 0, 0 };
1647		glClearBufferfv(GL_COLOR, 0, colorf);
1648		glViewport(0, 0, 100, 100);
1649
1650		program = CreateProgram(VertexShader().c_str(), FragmentShader().c_str());
1651		glBindAttribLocation(program, 0, "Vertex");
1652		glLinkProgram(program);
1653		if (!CheckProgram(program))
1654			return ERROR;
1655		glUseProgram(program);
1656
1657		glGenTextures(1, &tex);
1658		glBindTexture(GL_TEXTURE_2D, tex);
1659		std::vector<Vec4> data(100 * 100, Vec4(0.25, 0.5, 0.75, 1));
1660		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, &data[0]);
1661		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1662		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1663		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1664		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1665		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1666
1667		glGenVertexArrays(1, &vao);
1668		glBindVertexArray(vao);
1669		glGenBuffers(1, &vbo);
1670		glBindBuffer(GL_ARRAY_BUFFER, vbo);
1671		GLfloat buffData[16] = { -1, 1, 0, 1, -1, -1, 0, 1, 1, 1, 0, 1, 1, -1, 0, 1 };
1672		glBufferData(GL_ARRAY_BUFFER, sizeof(buffData), buffData, GL_STATIC_DRAW);
1673		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
1674		glEnableVertexAttribArray(0);
1675		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1676		glDisableVertexAttribArray(0);
1677		glDeleteVertexArrays(1, &vao);
1678		glBindBuffer(GL_ARRAY_BUFFER, 0);
1679
1680		glReadBuffer(GL_COLOR_ATTACHMENT0);
1681		std::vector<unsigned int> read(100 * 100 * 4, 0);
1682		glReadPixels(0, 0, 100, 100, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &read[0]);
1683		for (unsigned int i = 0; i < read.size() / 4; i += 4)
1684		{
1685			const GLfloat* rdata = (const GLfloat*)&read[i];
1686			Vec4		   rvec(rdata[0], rdata[1], rdata[2], rdata[3]);
1687			if (rvec != Vec4(0.75))
1688			{
1689				m_context.getTestContext().getLog()
1690					<< tcu::TestLog::Message << "Got: " << rvec.x() << " " << rvec.y() << " " << rvec.z() << " "
1691					<< rvec.w() << ", expected vec4(0.75)" << tcu::TestLog::EndMessage;
1692				return ERROR;
1693			}
1694		}
1695
1696		return NO_ERROR;
1697	}
1698
1699	virtual long Cleanup()
1700	{
1701		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1702		glDisableVertexAttribArray(0);
1703		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
1704		glDeleteTextures(1, &tex);
1705		glDeleteFramebuffers(1, &fbo);
1706		glDeleteRenderbuffers(1, &rbo);
1707		glDeleteVertexArrays(1, &vao);
1708		glDeleteBuffers(1, &vbo);
1709		glDeleteProgram(program);
1710		return NO_ERROR;
1711	}
1712};
1713
1714class PlainGatherFloat2DSrgb : public GatherBase
1715{
1716public:
1717	virtual std::string Expected()
1718	{
1719		return "vec4(0, 20.0/255.0, 90.0/255.0, 222.0/255.0)";
1720	}
1721
1722	virtual GLenum InternalFormat()
1723	{
1724		return GL_SRGB8_ALPHA8;
1725	}
1726
1727	virtual void Init()
1728	{
1729		CreateTextureSRGB();
1730	}
1731};
1732
1733class PlainGatherFloat2DSrgbAlpha : public GatherBase
1734{
1735public:
1736	virtual std::string Gather()
1737	{
1738		return "textureGather(my_sampler, vec2(p.x, p.y), 3)";
1739	}
1740
1741	virtual std::string Expected()
1742	{
1743		return "vec4(3.0/255.0, 7.0/255.0, 11.0/255.0, 15.0/255.0)";
1744	}
1745
1746	virtual GLenum InternalFormat()
1747	{
1748		return GL_SRGB8_ALPHA8;
1749	}
1750
1751	virtual void Init()
1752	{
1753		CreateTextureSRGB();
1754	}
1755};
1756
1757class PlainGatherFloat2DRgb : public GatherBase
1758{
1759public:
1760	virtual void Init()
1761	{
1762		CreateTexture2DRgb();
1763	}
1764};
1765
1766class PlainGatherFloat2DRg : public GatherBase
1767{
1768public:
1769	virtual void Init()
1770	{
1771		CreateTexture2DRg();
1772	}
1773};
1774
1775class PlainGatherFloat2DR : public GatherBase
1776{
1777public:
1778	virtual void Init()
1779	{
1780		CreateTexture2DR();
1781	}
1782};
1783
1784class OffsetGatherFloat2DRgb : public OffsetGatherFloat2D
1785{
1786public:
1787	virtual void Init()
1788	{
1789		CreateTexture2DRgb();
1790	}
1791};
1792
1793class OffsetGatherFloat2DRg : public OffsetGatherFloat2D
1794{
1795public:
1796	virtual void Init()
1797	{
1798		CreateTexture2DRg();
1799	}
1800};
1801
1802class OffsetGatherFloat2DR : public OffsetGatherFloat2D
1803{
1804public:
1805	virtual void Init()
1806	{
1807		CreateTexture2DR();
1808	}
1809};
1810
1811} // anonymous namespace
1812
1813TextureGatherTests::TextureGatherTests(glcts::Context& context) : TestCaseGroup(context, "texture_gather", "")
1814{
1815}
1816
1817TextureGatherTests::~TextureGatherTests(void)
1818{
1819}
1820
1821void TextureGatherTests::init()
1822{
1823	using namespace glcts;
1824	addChild(new TestSubcase(m_context, "api-enums", TestSubcase::Create<GatherEnumsTest>));
1825	addChild(new TestSubcase(m_context, "gather-glsl-compile", TestSubcase::Create<GatherGLSLCompile>));
1826	addChild(new TestSubcase(m_context, "plain-gather-float-2d", TestSubcase::Create<PlainGatherFloat2D>));
1827	addChild(new TestSubcase(m_context, "plain-gather-int-2d", TestSubcase::Create<PlainGatherInt2D>));
1828	addChild(new TestSubcase(m_context, "plain-gather-uint-2d", TestSubcase::Create<PlainGatherUint2D>));
1829	addChild(new TestSubcase(m_context, "plain-gather-depth-2d", TestSubcase::Create<PlainGatherDepth2D>));
1830	addChild(new TestSubcase(m_context, "plain-gather-float-2darray", TestSubcase::Create<PlainGatherFloat2DArray>));
1831	addChild(new TestSubcase(m_context, "plain-gather-int-2darray", TestSubcase::Create<PlainGatherInt2DArray>));
1832	addChild(new TestSubcase(m_context, "plain-gather-uint-2darray", TestSubcase::Create<PlainGatherUint2DArray>));
1833	addChild(new TestSubcase(m_context, "plain-gather-depth-2darray", TestSubcase::Create<PlainGatherDepth2DArray>));
1834	addChild(new TestSubcase(m_context, "plain-gather-float-cube-rgba", TestSubcase::Create<PlainGatherFloatCube>));
1835	addChild(new TestSubcase(m_context, "plain-gather-int-cube-rgba", TestSubcase::Create<PlainGatherIntCube>));
1836	addChild(new TestSubcase(m_context, "plain-gather-uint-cube", TestSubcase::Create<PlainGatherUintCube>));
1837	addChild(new TestSubcase(m_context, "plain-gather-depth-cube", TestSubcase::Create<PlainGatherDepthCube>));
1838	addChild(new TestSubcase(m_context, "offset-gather-float-2d", TestSubcase::Create<OffsetGatherFloat2D>));
1839	addChild(new TestSubcase(m_context, "offset-gather-int-2d", TestSubcase::Create<OffsetGatherInt2D>));
1840	addChild(new TestSubcase(m_context, "offset-gather-uint-2d", TestSubcase::Create<OffsetGatherUint2D>));
1841	addChild(new TestSubcase(m_context, "offset-gather-depth-2d", TestSubcase::Create<OffsetGatherDepth2D>));
1842	addChild(new TestSubcase(m_context, "offset-gather-float-2darray", TestSubcase::Create<OffsetGatherFloat2DArray>));
1843	addChild(new TestSubcase(m_context, "offset-gather-int-2darray", TestSubcase::Create<OffsetGatherInt2DArray>));
1844	addChild(new TestSubcase(m_context, "offset-gather-uint-2darray", TestSubcase::Create<OffsetGatherUint2DArray>));
1845	addChild(new TestSubcase(m_context, "offset-gather-depth-2darray", TestSubcase::Create<OffsetGatherDepth2DArray>));
1846	addChild(new TestSubcase(m_context, "swizzle", TestSubcase::Create<Swizzle>));
1847	addChild(new TestSubcase(m_context, "base-level", TestSubcase::Create<BaseLevel>));
1848	addChild(new TestSubcase(m_context, "incomplete-texture", TestSubcase::Create<IncompleteTexture>));
1849	addChild(
1850		new TestSubcase(m_context, "incomplete-texture-last-comp", TestSubcase::Create<IncompleteTextureLastComp>));
1851	addChild(new TestSubcase(m_context, "triangle-draw", TestSubcase::Create<TriangleDraw>));
1852	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb", TestSubcase::Create<PlainGatherFloat2DSrgb>));
1853	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb-alpha",
1854							 TestSubcase::Create<PlainGatherFloat2DSrgbAlpha>));
1855	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgb", TestSubcase::Create<PlainGatherFloat2DRgb>));
1856	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rg", TestSubcase::Create<PlainGatherFloat2DRg>));
1857	addChild(new TestSubcase(m_context, "plain-gather-float-2d-r", TestSubcase::Create<PlainGatherFloat2DR>));
1858	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rgb", TestSubcase::Create<OffsetGatherFloat2DRgb>));
1859	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rg", TestSubcase::Create<OffsetGatherFloat2DRg>));
1860	addChild(new TestSubcase(m_context, "offset-gather-float-2d-r", TestSubcase::Create<OffsetGatherFloat2DR>));
1861}
1862} // glcts namespace
1863