• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gl4cTextureGatherTests.hpp"
25 #include "glcTestSubcase.hpp"
26 #include "gluContextInfo.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "tcuImageCompare.hpp"
31 #include "tcuRenderTarget.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuVector.hpp"
35 #include <cstdarg>
36 #include <math.h>
37 #include <string>
38 #include <vector>
39 
40 namespace gl4cts
41 {
42 
43 using namespace glw;
44 using tcu::Vec4;
45 using tcu::Vec3;
46 using tcu::Vec2;
47 using tcu::IVec4;
48 using tcu::UVec4;
49 
50 namespace
51 {
52 
53 class TGBase : public deqp::SubcaseBase
54 {
55 public:
~TGBase()56 	virtual ~TGBase()
57 	{
58 	}
59 
TGBase()60 	TGBase() : renderTarget(m_context.getRenderContext().getRenderTarget()), pixelFormat(renderTarget.getPixelFormat())
61 	{
62 		g_color_eps = Vec4(1.f / (float)(1 << deMin32(8, pixelFormat.redBits)), 1.f / (float)(1 << deMin32(8, pixelFormat.greenBits)),
63 						   1.f / (float)(1 << deMin32(8, pixelFormat.blueBits)), 1.f / (float)(1 << pixelFormat.alphaBits));
64 	}
65 
66 	const tcu::RenderTarget& renderTarget;
67 	const tcu::PixelFormat&  pixelFormat;
68 	Vec4					 g_color_eps;
69 
GetWindowWidth()70 	int GetWindowWidth()
71 	{
72 		return renderTarget.getWidth();
73 	}
74 
GetWindowHeight()75 	int GetWindowHeight()
76 	{
77 		return renderTarget.getHeight();
78 	}
79 
Title()80 	virtual std::string Title()
81 	{
82 		return "";
83 	}
84 
Purpose()85 	virtual std::string Purpose()
86 	{
87 		return "";
88 	}
89 
Method()90 	virtual std::string Method()
91 	{
92 		return "";
93 	}
94 
PassCriteria()95 	virtual std::string PassCriteria()
96 	{
97 		return "";
98 	}
99 
CreateProgram(const char * src_vs,const char * src_tcs,const char * src_tes,const char * src_gs,const char * src_fs)100 	GLuint CreateProgram(const char* src_vs, const char* src_tcs, const char* src_tes, const char* src_gs,
101 						 const char* src_fs)
102 	{
103 		const GLuint p = glCreateProgram();
104 
105 		if (src_vs)
106 		{
107 			GLuint sh = glCreateShader(GL_VERTEX_SHADER);
108 			glAttachShader(p, sh);
109 			glDeleteShader(sh);
110 			glShaderSource(sh, 1, &src_vs, NULL);
111 			glCompileShader(sh);
112 		}
113 		if (src_tcs)
114 		{
115 			GLuint sh = glCreateShader(GL_TESS_CONTROL_SHADER);
116 			glAttachShader(p, sh);
117 			glDeleteShader(sh);
118 			glShaderSource(sh, 1, &src_tcs, NULL);
119 			glCompileShader(sh);
120 		}
121 		if (src_tes)
122 		{
123 			GLuint sh = glCreateShader(GL_TESS_EVALUATION_SHADER);
124 			glAttachShader(p, sh);
125 			glDeleteShader(sh);
126 			glShaderSource(sh, 1, &src_tes, NULL);
127 			glCompileShader(sh);
128 		}
129 		if (src_gs)
130 		{
131 			GLuint sh = glCreateShader(GL_GEOMETRY_SHADER);
132 			glAttachShader(p, sh);
133 			glDeleteShader(sh);
134 			glShaderSource(sh, 1, &src_gs, NULL);
135 			glCompileShader(sh);
136 		}
137 		if (src_fs)
138 		{
139 			GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
140 			glAttachShader(p, sh);
141 			glDeleteShader(sh);
142 			glShaderSource(sh, 1, &src_fs, NULL);
143 			glCompileShader(sh);
144 		}
145 		return p;
146 	}
147 
CreateComputeProgram(const std::string & cs)148 	GLuint CreateComputeProgram(const std::string& cs)
149 	{
150 		const GLuint p = glCreateProgram();
151 
152 		if (!cs.empty())
153 		{
154 			const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
155 			glAttachShader(p, sh);
156 			glDeleteShader(sh);
157 			const char* const src[1] = { cs.c_str() };
158 			glShaderSource(sh, 1, src, NULL);
159 			glCompileShader(sh);
160 		}
161 
162 		return p;
163 	}
164 
CheckProgram(GLuint program,bool * compile_error=NULL)165 	bool CheckProgram(GLuint program, bool* compile_error = NULL)
166 	{
167 		GLint compile_status = GL_TRUE;
168 		GLint status;
169 		glGetProgramiv(program, GL_LINK_STATUS, &status);
170 
171 		if (status == GL_FALSE)
172 		{
173 			GLint attached_shaders;
174 			glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
175 
176 			if (attached_shaders > 0)
177 			{
178 				std::vector<GLuint> shaders(attached_shaders);
179 				glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
180 
181 				for (GLint i = 0; i < attached_shaders; ++i)
182 				{
183 					GLenum type;
184 					glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
185 					switch (type)
186 					{
187 					case GL_VERTEX_SHADER:
188 						m_context.getTestContext().getLog()
189 							<< tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
190 						break;
191 					case GL_TESS_CONTROL_SHADER:
192 						m_context.getTestContext().getLog()
193 							<< tcu::TestLog::Message << "*** Tessellation Control Shader ***"
194 							<< tcu::TestLog::EndMessage;
195 						break;
196 					case GL_TESS_EVALUATION_SHADER:
197 						m_context.getTestContext().getLog()
198 							<< tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
199 							<< tcu::TestLog::EndMessage;
200 						break;
201 					case GL_GEOMETRY_SHADER:
202 						m_context.getTestContext().getLog()
203 							<< tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
204 						break;
205 					case GL_FRAGMENT_SHADER:
206 						m_context.getTestContext().getLog()
207 							<< tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
208 						break;
209 					case GL_COMPUTE_SHADER:
210 						m_context.getTestContext().getLog()
211 							<< tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
212 						break;
213 					default:
214 						m_context.getTestContext().getLog()
215 							<< tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
216 					}
217 
218 					GLint res;
219 					glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
220 					if (res != GL_TRUE)
221 						compile_status = res;
222 
223 					GLint length;
224 					glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
225 					if (length > 0)
226 					{
227 						std::vector<GLchar> source(length);
228 						glGetShaderSource(shaders[i], length, NULL, &source[0]);
229 						m_context.getTestContext().getLog()
230 							<< tcu::TestLog::Message << &source[0] << tcu::TestLog::EndMessage;
231 					}
232 
233 					glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
234 					if (length > 0)
235 					{
236 						std::vector<GLchar> log(length);
237 						glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
238 						m_context.getTestContext().getLog()
239 							<< tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
240 					}
241 				}
242 			}
243 
244 			GLint length;
245 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
246 			if (length > 0)
247 			{
248 				std::vector<GLchar> log(length);
249 				glGetProgramInfoLog(program, length, NULL, &log[0]);
250 				m_context.getTestContext().getLog() << tcu::TestLog::Message << &log[0] << tcu::TestLog::EndMessage;
251 			}
252 		}
253 
254 		if (compile_error)
255 			*compile_error = (compile_status == GL_TRUE ? false : true);
256 		if (compile_status != GL_TRUE)
257 			return false;
258 		return status == GL_TRUE ? true : false;
259 	}
260 
distance(GLfloat p0,GLfloat p1)261 	GLfloat distance(GLfloat p0, GLfloat p1)
262 	{
263 		return de::abs(p0 - p1);
264 	}
265 
ColorEqual(const Vec4 & c0,const Vec4 & c1,const Vec4 & epsilon)266 	inline bool ColorEqual(const Vec4& c0, const Vec4& c1, const Vec4& epsilon)
267 	{
268 		if (distance(c0.x(), c1.x()) > epsilon.x())
269 			return false;
270 		if (distance(c0.y(), c1.y()) > epsilon.y())
271 			return false;
272 		if (distance(c0.z(), c1.z()) > epsilon.z())
273 			return false;
274 		if (distance(c0.w(), c1.w()) > epsilon.w())
275 			return false;
276 		return true;
277 	}
278 
Setup()279 	virtual long Setup()
280 	{
281 		return NO_ERROR;
282 	}
283 
Cleanup()284 	virtual long Cleanup()
285 	{
286 		return NO_ERROR;
287 	}
288 };
289 
290 class GatherEnumsTest : public TGBase
291 {
Title()292 	virtual std::string Title()
293 	{
294 		return "Basic Enum Test";
295 	}
296 
Purpose()297 	virtual std::string Purpose()
298 	{
299 		return "Verify that gather related enums are correct.";
300 	}
301 
Method()302 	virtual std::string Method()
303 	{
304 		return "Query GL_*_TEXTURE_GATHER_OFFSET enums.";
305 	}
306 
PassCriteria()307 	virtual std::string PassCriteria()
308 	{
309 		return "Values of enums meet GL spec requirements.";
310 	}
311 
Run()312 	virtual long Run()
313 	{
314 		GLint res;
315 		glGetIntegerv(GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
316 		if (res > -8)
317 		{
318 			return ERROR;
319 		}
320 		glGetIntegerv(GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET, &res);
321 		if (res < 7)
322 		{
323 			return ERROR;
324 		}
325 		return NO_ERROR;
326 	}
327 };
328 
329 class GatherGLSLCompile : public TGBase
330 {
331 	GLuint program;
332 
Title()333 	virtual std::string Title()
334 	{
335 		return "GLSL Compile Test";
336 	}
337 
Purpose()338 	virtual std::string Purpose()
339 	{
340 		return "Verify that gather functions are visible in the shaders.";
341 	}
342 
Method()343 	virtual std::string Method()
344 	{
345 		return "Create shaders which use all types of gather functions.";
346 	}
347 
PassCriteria()348 	virtual std::string PassCriteria()
349 	{
350 		return "Programs compile and link successfuly.";
351 	}
352 
Uniforms()353 	virtual std::string Uniforms()
354 	{
355 		return "uniform sampler2D tex_2d;                  \n"
356 			   "uniform isamplerCube itex_cube;            \n"
357 			   "uniform usampler2DArray utex_2da;          \n"
358 			   "uniform isampler2DRect itex_2dr;           \n"
359 			   ""
360 			   "uniform sampler2DRectShadow tex_2drs;      \n"
361 			   "uniform sampler2DShadow tex_2ds;           \n"
362 			   "uniform samplerCubeShadow tex_cubes;       \n"
363 			   "uniform sampler2DArrayShadow tex_2das;     \n";
364 	}
365 
Sampling()366 	virtual std::string Sampling()
367 	{
368 		return "    textureGather(tex_2d,vec2(1));          \n"
369 			   "    textureGather(itex_cube,vec3(1));       \n"
370 			   "    textureGather(utex_2da,vec3(1));        \n"
371 			   "    textureGather(itex_2dr,vec2(1));        \n"
372 			   ""
373 			   "    textureGather(tex_2drs,vec2(1), 0.5);   \n"
374 			   "    textureGather(tex_2ds,vec2(1), 0.5);    \n"
375 			   "    textureGather(tex_cubes,vec3(1), 0.5);  \n"
376 			   "    textureGather(tex_2das,vec3(1), 0.5);   \n"
377 			   ""
378 			   "    textureGatherOffset(tex_2d,vec2(1), ivec2(0));          \n"
379 			   "    textureGatherOffset(utex_2da,vec3(1), ivec2(0));        \n"
380 			   "    textureGatherOffset(itex_2dr,vec2(1), ivec2(0));        \n"
381 			   ""
382 			   "    textureGatherOffset(tex_2drs,vec2(1), 0.5, ivec2(0));   \n"
383 			   "    textureGatherOffset(tex_2ds,vec2(1), 0.5, ivec2(0));    \n"
384 			   "    textureGatherOffset(tex_2das,vec3(1), 0.5, ivec2(0));   \n"
385 			   ""
386 			   "    const ivec2 offsets[4] = ivec2[](ivec2(0), ivec2(0), ivec2(0), ivec2(0)); \n"
387 			   "    textureGatherOffsets(tex_2d,vec2(1), offsets);          \n"
388 			   "    textureGatherOffsets(utex_2da,vec3(1), offsets);        \n"
389 			   "    textureGatherOffsets(itex_2dr,vec2(1), offsets);        \n"
390 			   ""
391 			   "    textureGatherOffsets(tex_2drs,vec2(1), 0.5, offsets);   \n"
392 			   "    textureGatherOffsets(tex_2ds,vec2(1), 0.5, offsets);    \n"
393 			   "    textureGatherOffsets(tex_2das,vec3(1), 0.5, offsets);   \n";
394 	}
395 
VertexShader()396 	virtual std::string VertexShader()
397 	{
398 		return "#version 400                               \n" + Uniforms() +
399 			   "  void main() {                            \n" + Sampling() +
400 			   "    gl_Position = vec4(1);                 \n"
401 			   "  }                                        \n";
402 	}
403 
FragmentShader()404 	virtual std::string FragmentShader()
405 	{
406 		return "#version 400                               \n"
407 			   "out vec4 color;                            \n" +
408 			   Uniforms() + "  void main() {                            \n" + Sampling() +
409 			   "    color = vec4(1);                       \n"
410 			   "  }                                        \n";
411 	}
412 
Run()413 	virtual long Run()
414 	{
415 		program = CreateProgram(VertexShader().c_str(), NULL, NULL, NULL, FragmentShader().c_str());
416 		glLinkProgram(program);
417 		if (!CheckProgram(program))
418 			return ERROR;
419 		return NO_ERROR;
420 	}
421 
Cleanup()422 	virtual long Cleanup()
423 	{
424 		glDeleteProgram(program);
425 		return NO_ERROR;
426 	}
427 };
428 
429 class GatherBase : public TGBase
430 {
431 public:
432 	GLuint tex, fbo, rbo, program, vao, vbo;
433 
CreateTexture2DRgb(bool base_level=false)434 	virtual GLvoid CreateTexture2DRgb(bool base_level = false)
435 	{
436 		GLenum		internal_format = GL_RGB32F;
437 		GLenum		format			= GL_RGB;
438 		const GLint csize			= base_level ? 64 : 32;
439 		GLint		size			= csize;
440 		GLenum		target			= GL_TEXTURE_2D;
441 		GLenum		tex_type		= GL_FLOAT;
442 
443 		glGenTextures(1, &tex);
444 		glBindTexture(target, tex);
445 		for (int i = 0; size > 0; ++i, size /= 2)
446 		{
447 			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
448 		}
449 		std::vector<Vec3> pixels(csize * csize, Vec3(1.0));
450 		glTexSubImage2D(target, 0, 0, 0, csize, csize, format, tex_type, &pixels[0]);
451 		glGenerateMipmap(target);
452 
453 		Vec3 data[4] = { Vec3(12. / 16, 13. / 16, 14. / 16), Vec3(8. / 16, 9. / 16, 10. / 16),
454 						 Vec3(0. / 16, 1. / 16, 2. / 16), Vec3(4. / 16, 5. / 16, 6. / 16) };
455 
456 		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
457 		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
458 		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
459 		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
460 		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
461 
462 		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
463 		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
464 		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
465 	}
466 
CreateTexture2DRg(bool base_level=false)467 	virtual GLvoid CreateTexture2DRg(bool base_level = false)
468 	{
469 		GLenum		internal_format = GL_RG32F;
470 		GLenum		format			= GL_RG;
471 		const GLint csize			= base_level ? 64 : 32;
472 		GLint		size			= csize;
473 		GLenum		target			= GL_TEXTURE_2D;
474 		GLenum		tex_type		= GL_FLOAT;
475 
476 		glGenTextures(1, &tex);
477 		glBindTexture(target, tex);
478 		for (int i = 0; size > 0; ++i, size /= 2)
479 		{
480 			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
481 		}
482 		std::vector<Vec2> pixels(csize * csize, Vec2(1.0));
483 		glTexSubImage2D(target, 0, 0, 0, csize, csize, format, tex_type, &pixels[0]);
484 		glGenerateMipmap(target);
485 
486 		Vec2 data[4] = { Vec2(12. / 16, 13. / 16), Vec2(8. / 16, 9. / 16), Vec2(0. / 16, 1. / 16),
487 						 Vec2(4. / 16, 5. / 16) };
488 
489 		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
490 		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
491 		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
492 		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
493 		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
494 
495 		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
496 		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
497 		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
498 	}
499 
CreateTexture2DR(bool base_level=false)500 	virtual GLvoid CreateTexture2DR(bool base_level = false)
501 	{
502 		GLenum		internal_format = GL_R32F;
503 		GLenum		format			= GL_RED;
504 		const GLint csize			= base_level ? 64 : 32;
505 		GLint		size			= csize;
506 		GLenum		target			= GL_TEXTURE_2D;
507 		GLenum		tex_type		= GL_FLOAT;
508 
509 		glGenTextures(1, &tex);
510 		glBindTexture(target, tex);
511 		for (int i = 0; size > 0; ++i, size /= 2)
512 		{
513 			glTexImage2D(target, i, internal_format, size, size, 0, format, tex_type, 0);
514 		}
515 		std::vector<GLfloat> pixels(csize * csize, 1.0);
516 		glTexSubImage2D(target, 0, 0, 0, csize, csize, format, tex_type, &pixels[0]);
517 		glGenerateMipmap(target);
518 
519 		GLfloat data[4] = { 12. / 16., 8. / 16., 0. / 16., 4. / 16. };
520 
521 		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, tex_type, data);
522 		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, tex_type, data + 0);
523 		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, tex_type, data + 1);
524 		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, tex_type, data + 2);
525 		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, tex_type, data + 3);
526 
527 		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
528 		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
529 		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
530 	}
531 
CreateTexture2DInt(bool rect=false)532 	virtual GLvoid CreateTexture2DInt(bool rect = false)
533 	{
534 		GLenum		internal_format = InternalFormat();
535 		const GLint csize			= 32;
536 		GLint		size			= csize;
537 		GLenum		target			= rect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
538 
539 		glGenTextures(1, &tex);
540 		glBindTexture(target, tex);
541 		if (!rect)
542 		{
543 			for (int i = 0; size > 0; ++i, size /= 2)
544 			{
545 				glTexImage2D(target, i, internal_format, size, size, 0, GL_RGBA_INTEGER, GL_INT, 0);
546 			}
547 		}
548 		else
549 		{
550 			glTexImage2D(target, 0, internal_format, size, size, 0, GL_RGBA_INTEGER, GL_INT, 0);
551 		}
552 		std::vector<IVec4> pixels(csize * csize, IVec4(999));
553 		glTexSubImage2D(target, 0, 0, 0, csize, csize, GL_RGBA_INTEGER, GL_INT, &pixels[0]);
554 
555 		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
556 
557 		glTexSubImage2D(target, 0, 22, 25, 2, 2, GL_RGBA_INTEGER, GL_INT, data);
558 		glTexSubImage2D(target, 0, 16, 10, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 0);
559 		glTexSubImage2D(target, 0, 11, 2, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 1);
560 		glTexSubImage2D(target, 0, 24, 13, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 2);
561 		glTexSubImage2D(target, 0, 9, 14, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 3);
562 
563 		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
564 		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
565 		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
566 		glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
567 		glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
568 	}
569 
CreateTexture2DArrayInt(int slices,int data_slice)570 	virtual GLvoid CreateTexture2DArrayInt(int slices, int data_slice)
571 	{
572 		GLenum		internal_format = InternalFormat();
573 		const GLint csize			= 32;
574 		GLint		size			= csize;
575 
576 		glGenTextures(1, &tex);
577 		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
578 		for (int i = 0; size > 0; ++i, size /= 2)
579 		{
580 			glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, GL_RGBA_INTEGER, GL_INT, 0);
581 		}
582 		std::vector<IVec4> pixels(csize * csize, IVec4(999));
583 		for (int i = 0; i < slices; ++i)
584 		{
585 			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, csize, csize, 1, GL_RGBA_INTEGER, GL_INT, &pixels[0]);
586 		}
587 
588 		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
589 
590 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, GL_RGBA_INTEGER, GL_INT, data);
591 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 0);
592 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 1);
593 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 2);
594 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 3);
595 
596 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
597 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
598 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
599 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
600 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
601 	}
602 
CreateTextureCubeArray(int slices,int data_slice)603 	virtual GLvoid CreateTextureCubeArray(int slices, int data_slice)
604 	{
605 		GLenum		internal_format = InternalFormat();
606 		GLenum		format			= Format();
607 		const GLint csize			= 32;
608 		GLint		size			= csize;
609 
610 		glGenTextures(1, &tex);
611 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
612 		for (int i = 0; size > 0; ++i, size /= 2)
613 		{
614 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, internal_format, size, size, 6 * slices, 0, format, GL_FLOAT, 0);
615 		}
616 		std::vector<Vec4> pixels(csize * csize, Vec4(1.0));
617 		for (int j = 0; j < 6 * slices; ++j)
618 		{
619 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, j, csize, csize, 1, format, GL_FLOAT, &pixels[0]);
620 		}
621 
622 		if (format != GL_DEPTH_COMPONENT)
623 		{
624 			glGenerateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY);
625 		}
626 
627 		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
628 						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
629 
630 		Vec4  depthData(data[0][0], data[1][0], data[2][0], data[3][0]);
631 		Vec4* packedData = (format == GL_DEPTH_COMPONENT) ? &depthData : data;
632 
633 		for (int i = 0; i < 6; ++i)
634 		{
635 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 22, 25, (6 * data_slice) + i, 2, 2, 1, format, GL_FLOAT,
636 							packedData);
637 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 16, 10, (6 * data_slice) + i, 1, 1, 1, format, GL_FLOAT,
638 							data + 0);
639 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 11, 2, (6 * data_slice) + i, 1, 1, 1, format, GL_FLOAT,
640 							data + 1);
641 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 24, 13, (6 * data_slice) + i, 1, 1, 1, format, GL_FLOAT,
642 							data + 2);
643 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 9, 14, (6 * data_slice) + i, 1, 1, 1, format, GL_FLOAT,
644 							data + 3);
645 		}
646 
647 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
648 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
649 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
650 	}
651 
CreateTextureCubeArrayInt(int slices,int data_slice)652 	virtual GLvoid CreateTextureCubeArrayInt(int slices, int data_slice)
653 	{
654 		GLenum		internal_format = InternalFormat();
655 		GLenum		format			= GL_RGBA_INTEGER;
656 		const GLint csize			= 32;
657 		GLint		size			= csize;
658 
659 		glGenTextures(1, &tex);
660 		glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
661 		for (int i = 0; size > 0; ++i, size /= 2)
662 		{
663 			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, internal_format, size, size, 6 * slices, 0, format, GL_INT, 0);
664 		}
665 		std::vector<IVec4> pixels(csize * csize, IVec4(999));
666 		for (int j = 0; j < 6 * slices; ++j)
667 		{
668 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, j, csize, csize, 1, format, GL_INT, &pixels[0]);
669 		}
670 
671 		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
672 
673 		for (int i = 0; i < 6; ++i)
674 		{
675 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 22, 25, (6 * data_slice) + i, 2, 2, 1, format, GL_INT, data);
676 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 9, 14, (6 * data_slice) + i, 1, 1, 1, format, GL_INT,
677 							data + 3);
678 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 16, 10, (6 * data_slice) + i, 1, 1, 1, format, GL_INT,
679 							data + 0);
680 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 11, 2, (6 * data_slice) + i, 1, 1, 1, format, GL_INT,
681 							data + 1);
682 			glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 24, 13, (6 * data_slice) + i, 1, 1, 1, format, GL_INT,
683 							data + 2);
684 		}
685 
686 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
687 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
688 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
689 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
690 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
691 	}
692 
CreateTexture2DArray(int slices,int data_slice)693 	virtual GLvoid CreateTexture2DArray(int slices, int data_slice)
694 	{
695 		GLenum		internal_format = InternalFormat();
696 		GLenum		format			= Format();
697 		const GLint csize			= 32;
698 		GLint		size			= csize;
699 
700 		glGenTextures(1, &tex);
701 		glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
702 		for (int i = 0; size > 0; ++i, size /= 2)
703 		{
704 			glTexImage3D(GL_TEXTURE_2D_ARRAY, i, internal_format, size, size, slices, 0, format, GL_FLOAT, 0);
705 		}
706 		std::vector<Vec4> pixels(csize * csize, Vec4(1.0));
707 		for (int i = 0; i < slices; ++i)
708 		{
709 			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, i, csize, csize, 1, format, GL_FLOAT, &pixels[0]);
710 		}
711 
712 		if (format != GL_DEPTH_COMPONENT)
713 		{
714 			glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
715 		}
716 
717 		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
718 						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
719 
720 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 22, 25, data_slice, 2, 2, 1, format, GL_FLOAT, data);
721 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 16, 10, data_slice, 1, 1, 1, format, GL_FLOAT, data + 0);
722 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 11, 2, data_slice, 1, 1, 1, format, GL_FLOAT, data + 1);
723 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 24, 13, data_slice, 1, 1, 1, format, GL_FLOAT, data + 2);
724 		glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 9, 14, data_slice, 1, 1, 1, format, GL_FLOAT, data + 3);
725 
726 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
727 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
728 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
729 	}
730 
CreateTextureCubeInt()731 	virtual GLvoid CreateTextureCubeInt()
732 	{
733 		GLenum		internal_format = InternalFormat();
734 		const GLint csize			= 32;
735 		GLint		size			= csize;
736 
737 		const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
738 								  GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
739 								  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
740 
741 		glGenTextures(1, &tex);
742 		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
743 		for (int i = 0; size > 0; ++i, size /= 2)
744 		{
745 			for (int j = 0; j < 6; ++j)
746 			{
747 				glTexImage2D(faces[j], i, internal_format, size, size, 0, GL_RGBA_INTEGER, GL_INT, 0);
748 			}
749 		}
750 		std::vector<IVec4> pixels(csize * csize, IVec4(999));
751 		for (int j = 0; j < 6; ++j)
752 		{
753 			glTexSubImage2D(faces[j], 0, 0, 0, csize, csize, GL_RGBA_INTEGER, GL_INT, &pixels[0]);
754 		}
755 
756 		IVec4 data[4] = { IVec4(12, 13, 14, 15), IVec4(8, 9, 10, 11), IVec4(0, 1, 2, 3), IVec4(4, 5, 6, 7) };
757 
758 		for (int j = 0; j < 6; ++j)
759 		{
760 			glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, GL_RGBA_INTEGER, GL_INT, data);
761 			glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 0);
762 			glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 1);
763 			glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 2);
764 			glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, GL_RGBA_INTEGER, GL_INT, data + 3);
765 		}
766 
767 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
768 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
769 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
770 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
771 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
772 	}
773 
CreateTextureCube()774 	virtual GLvoid CreateTextureCube()
775 	{
776 		GLenum		internal_format = InternalFormat();
777 		GLenum		format			= Format();
778 		const GLint csize			= 32;
779 		GLint		size			= csize;
780 
781 		const GLenum faces[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
782 								  GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
783 								  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
784 
785 		glGenTextures(1, &tex);
786 		glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
787 		for (int i = 0; size > 0; ++i, size /= 2)
788 		{
789 			for (int j = 0; j < 6; ++j)
790 			{
791 				glTexImage2D(faces[j], i, internal_format, size, size, 0, format, GL_FLOAT, 0);
792 			}
793 		}
794 		std::vector<Vec4> pixels(csize * csize, Vec4(1.0));
795 		for (int j = 0; j < 6; ++j)
796 		{
797 			glTexSubImage2D(faces[j], 0, 0, 0, csize, csize, format, GL_FLOAT, &pixels[0]);
798 		}
799 
800 		if (format != GL_DEPTH_COMPONENT)
801 		{
802 			glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
803 		}
804 
805 		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
806 						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
807 
808 		Vec4  depthData(data[0][0], data[1][0], data[2][0], data[3][0]);
809 		Vec4* packedData = (format == GL_DEPTH_COMPONENT) ? &depthData : data;
810 
811 		for (int j = 0; j < 6; ++j)
812 		{
813 			glTexSubImage2D(faces[j], 0, 22, 25, 2, 2, format, GL_FLOAT, packedData);
814 			glTexSubImage2D(faces[j], 0, 16, 10, 1, 1, format, GL_FLOAT, data + 0);
815 			glTexSubImage2D(faces[j], 0, 11, 2, 1, 1, format, GL_FLOAT, data + 1);
816 			glTexSubImage2D(faces[j], 0, 24, 13, 1, 1, format, GL_FLOAT, data + 2);
817 			glTexSubImage2D(faces[j], 0, 9, 14, 1, 1, format, GL_FLOAT, data + 3);
818 		}
819 
820 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
821 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
822 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
823 	}
824 
CreateTexture2D(bool rect=false,bool base_level=false)825 	virtual GLvoid CreateTexture2D(bool rect = false, bool base_level = false)
826 	{
827 		GLenum		internal_format = InternalFormat();
828 		GLenum		format			= Format();
829 		const GLint csize			= base_level ? 64 : 32;
830 		GLint		size			= csize;
831 		GLenum		target			= rect ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
832 
833 		glGenTextures(1, &tex);
834 		glBindTexture(target, tex);
835 		if (!rect)
836 		{
837 			for (int i = 0; size > 0; ++i, size /= 2)
838 			{
839 				glTexImage2D(target, i, internal_format, size, size, 0, format, GL_FLOAT, 0);
840 			}
841 		}
842 		else
843 		{
844 			glTexImage2D(target, 0, internal_format, size, size, 0, format, GL_FLOAT, 0);
845 		}
846 		std::vector<Vec4> pixels(csize * csize, Vec4(1.0));
847 		glTexSubImage2D(target, 0, 0, 0, csize, csize, format, GL_FLOAT, &pixels[0]);
848 
849 		if (!rect && format != GL_DEPTH_COMPONENT)
850 		{
851 			glGenerateMipmap(target);
852 		}
853 
854 		Vec4 data[4] = { Vec4(12. / 16, 13. / 16, 14. / 16, 15. / 16), Vec4(8. / 16, 9. / 16, 10. / 16, 11. / 16),
855 						 Vec4(0. / 16, 1. / 16, 2. / 16, 3. / 16), Vec4(4. / 16, 5. / 16, 6. / 16, 7. / 16) };
856 
857 		glTexSubImage2D(target, base_level, 22, 25, 2, 2, format, GL_FLOAT, data);
858 		glTexSubImage2D(target, base_level, 16, 10, 1, 1, format, GL_FLOAT, data + 0);
859 		glTexSubImage2D(target, base_level, 11, 2, 1, 1, format, GL_FLOAT, data + 1);
860 		glTexSubImage2D(target, base_level, 24, 13, 1, 1, format, GL_FLOAT, data + 2);
861 		glTexSubImage2D(target, base_level, 9, 14, 1, 1, format, GL_FLOAT, data + 3);
862 
863 		glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
864 		glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
865 		glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
866 
867 		if (base_level)
868 			glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 1);
869 	}
870 
FallthroughVertexShader()871 	virtual std::string FallthroughVertexShader()
872 	{
873 		return "#version 400                     \n"
874 			   "in vec4 v_in_0;                  \n"
875 			   "flat out vec4 v_out_0;           \n"
876 			   "void main() {                    \n"
877 			   "    gl_Position = vec4(0,0,0,1);                \n"
878 			   "    v_out_0 = v_in_0;                           \n"
879 			   "}";
880 	}
881 
FallthroughFragmentShader()882 	virtual std::string FallthroughFragmentShader()
883 	{
884 		return "#version 400                     \n"
885 			   "out " +
886 			   Type() + " f_out_0;                \n"
887 						"flat in " +
888 			   Type() + " v_out_0;            \n"
889 						"void main() {                    \n"
890 						"    f_out_0 = v_out_0;           \n"
891 						"}";
892 	}
893 
TestFunction()894 	virtual std::string TestFunction()
895 	{
896 		return Sampler() + TextBody();
897 	}
898 
Type()899 	virtual std::string Type()
900 	{
901 		return "vec4";
902 	}
903 
Sampler()904 	virtual std::string Sampler()
905 	{
906 		return "uniform sampler2D my_sampler;                      \n";
907 	}
908 
TextBody()909 	virtual std::string TextBody()
910 	{
911 		return Type() + " test_function(vec4 p) {                       \n"
912 						"    return textureGather(my_sampler, vec2(p.x, p.y));           \n"
913 						"}\n";
914 	}
915 
VertexShader()916 	virtual std::string VertexShader()
917 	{
918 		return "#version 400                                       \n"
919 			   "#extension GL_ARB_texture_cube_map_array : enable  \n"
920 			   ""
921 			   "in vec4 v_in_0;                                    \n"
922 			   "flat out " +
923 			   Type() + " v_out_0;                   \n" + TestFunction() +
924 			   "void main() {                                      \n"
925 			   "    gl_Position = vec4(0,0,0,1);                   \n"
926 			   "    v_out_0 = test_function(v_in_0);               \n"
927 			   "}";
928 	}
929 
FragmentShader()930 	virtual std::string FragmentShader()
931 	{
932 		return "#version 400                                       \n"
933 			   "#extension GL_ARB_texture_cube_map_array : enable  \n"
934 			   ""
935 			   "flat in vec4 v_out_0;                              \n"
936 			   "out " +
937 			   Type() + " f_out_0;                        \n" + TestFunction() +
938 			   "void main() {                                      \n"
939 			   "    f_out_0 = test_function(v_out_0);              \n"
940 			   "}";
941 	}
942 
ComputeShader()943 	virtual std::string ComputeShader()
944 	{
945 		return "#version 420 core                                           \n"
946 			   "#extension GL_ARB_shader_storage_buffer_object : require    \n"
947 			   "#extension GL_ARB_compute_shader : require            \n"
948 			   "#extension GL_ARB_texture_cube_map_array : enable     \n"
949 			   "layout(local_size_x = 1, local_size_y = 1) in;        \n"
950 			   "layout(std430) buffer Output {                        \n"
951 			   "  " +
952 			   Type() + " data;                                \n"
953 						"} g_out;                                              \n"
954 						"uniform vec4 cs_in;                                   \n" +
955 			   TestFunction() + "void main() {                                         \n"
956 								"  g_out.data = test_function(cs_in);                  \n"
957 								"}                                                     \n";
958 	}
959 
Init()960 	virtual void Init()
961 	{
962 		CreateTexture2D();
963 	}
964 
SetRbo()965 	virtual void SetRbo()
966 	{
967 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1);
968 	}
969 
Verify()970 	virtual long Verify()
971 	{
972 		Vec4 data;
973 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, &data);
974 		if (!ColorEqual(data, Expected(), g_color_eps))
975 		{
976 			m_context.getTestContext().getLog()
977 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
978 				<< Expected().z() << ", " << Expected().w() << ", got: " << data.x() << ", " << data.y() << ", "
979 				<< data.z() << ", " << data.w() << ", epsilon: " << g_color_eps.x() << ", " << g_color_eps.y() << ", "
980 				<< g_color_eps.z() << ", " << g_color_eps.w() << tcu::TestLog::EndMessage;
981 			return ERROR;
982 		}
983 		return NO_ERROR;
984 	}
985 
Expected()986 	virtual Vec4 Expected()
987 	{
988 		return Vec4(0. / 16, 4. / 16, 8. / 16, 12. / 16);
989 	}
990 
InternalFormat()991 	virtual GLenum InternalFormat()
992 	{
993 		return GL_RGBA32F;
994 	}
995 
Format()996 	virtual GLenum Format()
997 	{
998 		return GL_RGBA;
999 	}
1000 
BufferData()1001 	virtual Vec4 BufferData()
1002 	{
1003 		return Vec4(23. / 32, 26. / 32, 5, 3);
1004 	}
1005 
Supported()1006 	virtual bool Supported()
1007 	{
1008 		return true;
1009 	}
1010 
Run()1011 	virtual long Run()
1012 	{
1013 
1014 		if (!Supported())
1015 			return NO_ERROR;
1016 		Init();
1017 
1018 		glGenFramebuffers(1, &fbo);
1019 		glGenRenderbuffers(1, &rbo);
1020 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1021 		SetRbo();
1022 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1023 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1024 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
1025 		glDrawBuffers(1, &drawBuffer);
1026 		GLfloat colorf[4] = { 0, 0, 0, 0 };
1027 		glClearBufferfv(GL_COLOR, 0, colorf);
1028 		glViewport(0, 0, 1, 1);
1029 
1030 		glGenVertexArrays(1, &vao);
1031 		glBindVertexArray(vao);
1032 		glGenBuffers(1, &vbo);
1033 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
1034 		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
1035 		glEnableVertexAttribArray(0);
1036 		Vec4 buffData = BufferData();
1037 		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
1038 
1039 		for (int i = 0; i < 2; ++i)
1040 		{
1041 			if (i == 0)
1042 				program = CreateProgram(VertexShader().c_str(), NULL, NULL, NULL, FallthroughFragmentShader().c_str());
1043 			else
1044 				program = CreateProgram(FallthroughVertexShader().c_str(), NULL, NULL, NULL, FragmentShader().c_str());
1045 			glBindAttribLocation(program, 0, "v_in_0");
1046 			glBindFragDataLocation(program, 0, "f_out_0");
1047 			glLinkProgram(program);
1048 			if (!CheckProgram(program))
1049 				return ERROR;
1050 			glUseProgram(program);
1051 
1052 			glDrawArrays(GL_POINTS, 0, 1);
1053 			glReadBuffer(GL_COLOR_ATTACHMENT0);
1054 
1055 			glDeleteProgram(program);
1056 
1057 			if (Verify() == ERROR)
1058 				return ERROR;
1059 		}
1060 
1061 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
1062 		{
1063 			m_context.getTestContext().getLog()
1064 				<< tcu::TestLog::Message << "Expected "
1065 				<< "GL_ARB_compute_shader or GL_ARB_compute_shader not supported, skipping compute stage"
1066 				<< tcu::TestLog::EndMessage;
1067 			return NO_ERROR;
1068 		}
1069 		else
1070 		{
1071 			return TestCompute();
1072 		}
1073 	}
1074 
TestCompute()1075 	virtual long TestCompute()
1076 	{
1077 		GLuint m_buffer;
1078 
1079 		program = CreateComputeProgram(ComputeShader());
1080 		glLinkProgram(program);
1081 		if (!CheckProgram(program))
1082 			return ERROR;
1083 		glUseProgram(program);
1084 
1085 		glUniform4f(glGetUniformLocation(program, "cs_in"), BufferData().x(), BufferData().y(), BufferData().z(),
1086 					BufferData().w());
1087 
1088 		glGenBuffers(1, &m_buffer);
1089 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1090 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Vec4), NULL, GL_DYNAMIC_DRAW);
1091 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1092 
1093 		glDispatchCompute(1, 1, 1);
1094 
1095 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
1096 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1097 		long error = VerifyCompute();
1098 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1099 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1100 		glDeleteBuffers(1, &m_buffer);
1101 
1102 		return error;
1103 	}
1104 
VerifyCompute()1105 	virtual long VerifyCompute()
1106 	{
1107 		Vec4* data;
1108 		data = static_cast<Vec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Vec4), GL_MAP_READ_BIT));
1109 		if (!ColorEqual(data[0], Expected(), g_color_eps))
1110 		{ // for unorms
1111 			m_context.getTestContext().getLog()
1112 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1113 				<< Expected().z() << ", " << Expected().w() << " got: " << data[0].x() << ", " << data[0].y() << ", "
1114 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1115 			return ERROR;
1116 		}
1117 		return NO_ERROR;
1118 	}
1119 
Cleanup()1120 	virtual long Cleanup()
1121 	{
1122 		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
1123 		glDisableVertexAttribArray(0);
1124 		glDeleteTextures(1, &tex);
1125 		glDeleteVertexArrays(1, &vao);
1126 		glDeleteBuffers(1, &vbo);
1127 		glDeleteRenderbuffers(1, &rbo);
1128 		glDeleteFramebuffers(1, &fbo);
1129 		glDeleteProgram(program);
1130 		return NO_ERROR;
1131 	}
1132 };
1133 
1134 class PlainGatherFloat2DRgba : public GatherBase
1135 {
1136 };
1137 
1138 class PlainGatherFloat2DRg : public GatherBase
1139 {
1140 public:
TestFunction()1141 	virtual std::string TestFunction()
1142 	{
1143 		return "uniform sampler2D my_sampler;                                   \n"
1144 			   ""
1145 			   "vec4 test_function(vec4 p) {                                    \n"
1146 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 1);        \n"
1147 			   "}\n";
1148 	}
1149 
Expected()1150 	virtual Vec4 Expected()
1151 	{
1152 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
1153 	}
1154 
InternalFormat()1155 	virtual GLenum InternalFormat()
1156 	{
1157 		return GL_RG32F;
1158 	}
1159 };
1160 
1161 class PlainGatherUnorm2D : public GatherBase
1162 {
1163 public:
InternalFormat()1164 	virtual GLenum InternalFormat()
1165 	{
1166 		return GL_RGBA16;
1167 	}
1168 
TestFunction()1169 	virtual std::string TestFunction()
1170 	{
1171 		return "uniform sampler2D my_sampler;                                   \n"
1172 			   ""
1173 			   "vec4 test_function(vec4 p) {                                    \n"
1174 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 0);        \n"
1175 			   "}\n";
1176 	}
1177 };
1178 
1179 class PlainGatherInt2DRgba : public GatherBase
1180 {
1181 public:
InternalFormat()1182 	virtual GLenum InternalFormat()
1183 	{
1184 		return GL_RGBA32I;
1185 	}
1186 
Init()1187 	virtual void Init()
1188 	{
1189 		CreateTexture2DInt();
1190 	}
1191 
SetRbo()1192 	virtual void SetRbo()
1193 	{
1194 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
1195 	}
1196 
Verify()1197 	virtual long Verify()
1198 	{
1199 		IVec4 data;
1200 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
1201 		if (data != IVec4(0, 4, 8, 12))
1202 		{
1203 			m_context.getTestContext().getLog()
1204 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
1205 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1206 			return ERROR;
1207 		}
1208 		return NO_ERROR;
1209 	}
1210 
VerifyCompute()1211 	virtual long VerifyCompute()
1212 	{
1213 		IVec4* data;
1214 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1215 		if (data[0] != IVec4(0, 4, 8, 12))
1216 		{
1217 			m_context.getTestContext().getLog()
1218 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1219 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1220 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1221 			return ERROR;
1222 		}
1223 		return NO_ERROR;
1224 	}
1225 
Sampler()1226 	virtual std::string Sampler()
1227 	{
1228 		return "uniform isampler2D my_sampler;                     \n";
1229 	}
1230 
Type()1231 	virtual std::string Type()
1232 	{
1233 		return "ivec4";
1234 	}
1235 };
1236 
1237 class PlainGatherInt2DRg : public PlainGatherInt2DRgba
1238 {
1239 public:
InternalFormat()1240 	virtual GLenum InternalFormat()
1241 	{
1242 		return GL_RG32I;
1243 	}
1244 };
1245 
1246 class PlainGatherUint2D : public GatherBase
1247 {
1248 public:
InternalFormat()1249 	virtual GLenum InternalFormat()
1250 	{
1251 		return GL_RGBA32UI;
1252 	}
1253 
Init()1254 	virtual void Init()
1255 	{
1256 		CreateTexture2DInt();
1257 	}
1258 
SetRbo()1259 	virtual void SetRbo()
1260 	{
1261 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
1262 	}
1263 
Verify()1264 	virtual long Verify()
1265 	{
1266 		IVec4 data;
1267 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
1268 		if (data != IVec4(2, 6, 10, 14))
1269 		{
1270 			m_context.getTestContext().getLog()
1271 				<< tcu::TestLog::Message << "Expected 2, 6, 10, 14, got: " << data.x() << ", " << data.y() << ", "
1272 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1273 			return ERROR;
1274 		}
1275 		return NO_ERROR;
1276 	}
1277 
VerifyCompute()1278 	virtual long VerifyCompute()
1279 	{
1280 		IVec4* data;
1281 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1282 		if (data[0] != IVec4(2, 6, 10, 14))
1283 		{
1284 			m_context.getTestContext().getLog()
1285 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1286 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1287 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1288 			return ERROR;
1289 		}
1290 		return NO_ERROR;
1291 	}
1292 
Sampler()1293 	virtual std::string Sampler()
1294 	{
1295 		return "uniform usampler2D my_sampler;                     \n";
1296 	}
1297 
BufferData()1298 	virtual Vec4 BufferData()
1299 	{
1300 		return Vec4(22.9f / 32, 25.9f / 32, 2, 2);
1301 	}
1302 
Type()1303 	virtual std::string Type()
1304 	{
1305 		return "uvec4";
1306 	}
1307 
TextBody()1308 	virtual std::string TextBody()
1309 	{
1310 		return Type() + " test_function(vec4 p) {                                   \n"
1311 						"    return textureGather(my_sampler, vec2(p.x, p.y), 2);            \n"
1312 						"}\n";
1313 	}
1314 };
1315 
1316 class PlainGatherDepth2D : public GatherBase
1317 {
1318 public:
InternalFormat()1319 	virtual GLenum InternalFormat()
1320 	{
1321 		return GL_DEPTH_COMPONENT32F;
1322 	}
1323 
Format()1324 	virtual GLenum Format()
1325 	{
1326 		return GL_DEPTH_COMPONENT;
1327 	}
1328 
Init()1329 	virtual void Init()
1330 	{
1331 		CreateTexture2D();
1332 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1333 	}
1334 
Expected()1335 	virtual Vec4 Expected()
1336 	{
1337 		return Vec4(1, 1, 0, 0);
1338 	}
1339 
BufferData()1340 	virtual Vec4 BufferData()
1341 	{
1342 		return Vec4(23. / 32, 26. / 32, 13.5 / 16, 3);
1343 	}
1344 
Sampler()1345 	virtual std::string Sampler()
1346 	{
1347 		return "uniform sampler2DShadow my_sampler;                     \n";
1348 	}
1349 
TextBody()1350 	virtual std::string TextBody()
1351 	{
1352 		return Type() + " test_function(vec4 p) {                                \n"
1353 						"    return textureGather(my_sampler, vec2(p.x, p.y), p.z);       \n"
1354 						"}\n";
1355 	}
1356 };
1357 
1358 class PlainGatherFloat2DArray : public GatherBase
1359 {
1360 public:
Init()1361 	virtual void Init()
1362 	{
1363 		CreateTexture2DArray(9, 5);
1364 	}
1365 
Sampler()1366 	virtual std::string Sampler()
1367 	{
1368 		return "uniform sampler2DArray my_sampler;                     \n";
1369 	}
1370 
TextBody()1371 	virtual std::string TextBody()
1372 	{
1373 		return Type() + " test_function(vec4 p) {                                \n"
1374 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
1375 						"}\n";
1376 	}
1377 };
1378 
1379 class PlainGatherUnorm2DArray : public GatherBase
1380 {
1381 public:
Init()1382 	virtual void Init()
1383 	{
1384 		CreateTexture2DArray(7, 3);
1385 	}
1386 
Sampler()1387 	virtual std::string Sampler()
1388 	{
1389 		return "uniform sampler2DArray my_sampler;                     \n";
1390 	}
1391 
TextBody()1392 	virtual std::string TextBody()
1393 	{
1394 		return Type() + " test_function(vec4 p) {                                \n"
1395 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.w));       \n"
1396 						"}\n";
1397 	}
1398 
InternalFormat()1399 	virtual GLenum InternalFormat()
1400 	{
1401 		return GL_RGBA16;
1402 	}
1403 };
1404 
1405 class PlainGatherInt2DArray : public GatherBase
1406 {
1407 public:
Init()1408 	virtual void Init()
1409 	{
1410 		CreateTexture2DArrayInt(20, 11);
1411 	}
1412 
InternalFormat()1413 	virtual GLenum InternalFormat()
1414 	{
1415 		return GL_RGBA32I;
1416 	}
1417 
SetRbo()1418 	virtual void SetRbo()
1419 	{
1420 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
1421 	}
1422 
Verify()1423 	virtual long Verify()
1424 	{
1425 		IVec4 data;
1426 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
1427 		if (data != IVec4(3, 7, 11, 15))
1428 		{
1429 			m_context.getTestContext().getLog()
1430 				<< tcu::TestLog::Message << "Expected 3, 7, 11, 15, got: " << data.x() << ", " << data.y() << ", "
1431 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1432 			return ERROR;
1433 		}
1434 		return NO_ERROR;
1435 	}
1436 
VerifyCompute()1437 	virtual long VerifyCompute()
1438 	{
1439 		IVec4* data;
1440 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1441 		if (data[0] != IVec4(3, 7, 11, 15))
1442 		{
1443 			m_context.getTestContext().getLog()
1444 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1445 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1446 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1447 			return ERROR;
1448 		}
1449 		return NO_ERROR;
1450 	}
1451 
Type()1452 	virtual std::string Type()
1453 	{
1454 		return "ivec4";
1455 	}
1456 
BufferData()1457 	virtual Vec4 BufferData()
1458 	{
1459 		return Vec4(23. / 32, 26. / 32, 11, 3);
1460 	}
1461 
Sampler()1462 	virtual std::string Sampler()
1463 	{
1464 		return "uniform isampler2DArray my_sampler;                     \n";
1465 	}
1466 
TextBody()1467 	virtual std::string TextBody()
1468 	{
1469 		return Type() + " test_function(vec4 p) {                                \n"
1470 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 3);    \n"
1471 						"}\n";
1472 	}
1473 };
1474 
1475 class PlainGatherUint2DArray : public GatherBase
1476 {
1477 public:
Init()1478 	virtual void Init()
1479 	{
1480 		CreateTexture2DArrayInt(3, 1);
1481 	}
1482 
InternalFormat()1483 	virtual GLenum InternalFormat()
1484 	{
1485 		return GL_RGBA32UI;
1486 	}
1487 
SetRbo()1488 	virtual void SetRbo()
1489 	{
1490 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
1491 	}
1492 
Verify()1493 	virtual long Verify()
1494 	{
1495 		IVec4 data;
1496 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
1497 		if (data != IVec4(0, 4, 8, 12))
1498 		{
1499 			m_context.getTestContext().getLog()
1500 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
1501 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1502 			return ERROR;
1503 		}
1504 		return NO_ERROR;
1505 	}
1506 
VerifyCompute()1507 	virtual long VerifyCompute()
1508 	{
1509 		IVec4* data;
1510 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1511 		if (data[0] != IVec4(0, 4, 8, 12))
1512 		{
1513 			m_context.getTestContext().getLog()
1514 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1515 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1516 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1517 			return ERROR;
1518 		}
1519 		return NO_ERROR;
1520 	}
1521 
Type()1522 	virtual std::string Type()
1523 	{
1524 		return "uvec4";
1525 	}
1526 
BufferData()1527 	virtual Vec4 BufferData()
1528 	{
1529 		return Vec4(23. / 32, 26. / 32, 1, 3);
1530 	}
1531 
Sampler()1532 	virtual std::string Sampler()
1533 	{
1534 		return "uniform usampler2DArray my_sampler;                     \n";
1535 	}
1536 
TextBody()1537 	virtual std::string TextBody()
1538 	{
1539 		return Type() + " test_function(vec4 p) {                                \n"
1540 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
1541 						"}\n";
1542 	}
1543 };
1544 
1545 class PlainGatherDepth2DArray : public GatherBase
1546 {
1547 public:
InternalFormat()1548 	virtual GLenum InternalFormat()
1549 	{
1550 		return GL_DEPTH_COMPONENT32F;
1551 	}
1552 
Format()1553 	virtual GLenum Format()
1554 	{
1555 		return GL_DEPTH_COMPONENT;
1556 	}
1557 
Init()1558 	virtual void Init()
1559 	{
1560 		CreateTexture2DArray(9, 5);
1561 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1562 	}
1563 
Expected()1564 	virtual Vec4 Expected()
1565 	{
1566 		return Vec4(1, 1, 0, 0);
1567 	}
1568 
BufferData()1569 	virtual Vec4 BufferData()
1570 	{
1571 		return Vec4(23. / 32, 26. / 32, 5, 13.5 / 16);
1572 	}
1573 
Sampler()1574 	virtual std::string Sampler()
1575 	{
1576 		return "uniform sampler2DArrayShadow my_sampler;                     \n";
1577 	}
1578 
TextBody()1579 	virtual std::string TextBody()
1580 	{
1581 		return Type() + " test_function(vec4 p) {                                \n"
1582 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w);       \n"
1583 						"}\n";
1584 	}
1585 };
1586 
1587 class PlainGatherFloatCubeRgba : public GatherBase
1588 {
1589 public:
Init()1590 	virtual void Init()
1591 	{
1592 		CreateTextureCube();
1593 	}
1594 
BufferData()1595 	virtual Vec4 BufferData()
1596 	{
1597 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1598 	}
1599 
Sampler()1600 	virtual std::string Sampler()
1601 	{
1602 		return "uniform samplerCube my_sampler;                     \n";
1603 	}
1604 
TextBody()1605 	virtual std::string TextBody()
1606 	{
1607 		return Type() + " test_function(vec4 p) {                                \n"
1608 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
1609 						"}\n";
1610 	}
1611 };
1612 
1613 class PlainGatherFloatCubeRg : public GatherBase
1614 {
1615 public:
Init()1616 	virtual void Init()
1617 	{
1618 		CreateTextureCube();
1619 	}
1620 
BufferData()1621 	virtual Vec4 BufferData()
1622 	{
1623 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1624 	}
1625 
Sampler()1626 	virtual std::string Sampler()
1627 	{
1628 		return "uniform samplerCube my_sampler;                     \n";
1629 	}
1630 
TextBody()1631 	virtual std::string TextBody()
1632 	{
1633 		return Type() + " test_function(vec4 p) {                                \n"
1634 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 1);    \n"
1635 						"}\n";
1636 	}
1637 
Expected()1638 	virtual Vec4 Expected()
1639 	{
1640 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
1641 	}
1642 
InternalFormat()1643 	virtual GLenum InternalFormat()
1644 	{
1645 		return GL_RG32F;
1646 	}
1647 };
1648 
1649 class PlainGatherUnormCube : public GatherBase
1650 {
1651 public:
Init()1652 	virtual void Init()
1653 	{
1654 		CreateTextureCube();
1655 	}
1656 
BufferData()1657 	virtual Vec4 BufferData()
1658 	{
1659 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1660 	}
1661 
Sampler()1662 	virtual std::string Sampler()
1663 	{
1664 		return "uniform samplerCube my_sampler;                     \n";
1665 	}
1666 
TextBody()1667 	virtual std::string TextBody()
1668 	{
1669 		return Type() + " test_function(vec4 p) {                                \n"
1670 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
1671 						"}\n";
1672 	}
1673 
InternalFormat()1674 	virtual GLenum InternalFormat()
1675 	{
1676 		return GL_RGBA16;
1677 	}
1678 };
1679 
1680 class PlainGatherIntCubeRgba : public GatherBase
1681 {
1682 public:
Init()1683 	virtual void Init()
1684 	{
1685 		CreateTextureCubeInt();
1686 	}
1687 
BufferData()1688 	virtual Vec4 BufferData()
1689 	{
1690 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1691 	}
1692 
Sampler()1693 	virtual std::string Sampler()
1694 	{
1695 		return "uniform isamplerCube my_sampler;                     \n";
1696 	}
1697 
TextBody()1698 	virtual std::string TextBody()
1699 	{
1700 		return Type() + " test_function(vec4 p) {                                \n"
1701 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
1702 						"}\n";
1703 	}
1704 
InternalFormat()1705 	virtual GLenum InternalFormat()
1706 	{
1707 		return GL_RGBA32I;
1708 	}
1709 
SetRbo()1710 	virtual void SetRbo()
1711 	{
1712 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
1713 	}
1714 
Verify()1715 	virtual long Verify()
1716 	{
1717 		IVec4 data;
1718 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
1719 		if (data != IVec4(0, 4, 8, 12))
1720 		{
1721 			m_context.getTestContext().getLog()
1722 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
1723 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1724 			return ERROR;
1725 		}
1726 		return NO_ERROR;
1727 	}
1728 
VerifyCompute()1729 	virtual long VerifyCompute()
1730 	{
1731 		IVec4* data;
1732 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1733 		if (data[0] != IVec4(0, 4, 8, 12))
1734 		{
1735 			m_context.getTestContext().getLog()
1736 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1737 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1738 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1739 			return ERROR;
1740 		}
1741 		return NO_ERROR;
1742 	}
1743 
Type()1744 	virtual std::string Type()
1745 	{
1746 		return "ivec4";
1747 	}
1748 };
1749 
1750 class PlainGatherIntCubeRg : public GatherBase
1751 {
1752 public:
Init()1753 	virtual void Init()
1754 	{
1755 		CreateTextureCubeInt();
1756 	}
1757 
BufferData()1758 	virtual Vec4 BufferData()
1759 	{
1760 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1761 	}
1762 
Sampler()1763 	virtual std::string Sampler()
1764 	{
1765 		return "uniform isamplerCube my_sampler;                     \n";
1766 	}
1767 
TextBody()1768 	virtual std::string TextBody()
1769 	{
1770 		return Type() + " test_function(vec4 p) {                                \n"
1771 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 1);    \n"
1772 						"}\n";
1773 	}
1774 
InternalFormat()1775 	virtual GLenum InternalFormat()
1776 	{
1777 		return GL_RG32I;
1778 	}
1779 
SetRbo()1780 	virtual void SetRbo()
1781 	{
1782 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
1783 	}
1784 
Verify()1785 	virtual long Verify()
1786 	{
1787 		IVec4 data;
1788 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
1789 		if (data != IVec4(1, 5, 9, 13))
1790 		{
1791 			m_context.getTestContext().getLog()
1792 				<< tcu::TestLog::Message << "Expected 1, 5, 9, 13, got: " << data.x() << ", " << data.y() << ", "
1793 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1794 			return ERROR;
1795 		}
1796 		return NO_ERROR;
1797 	}
1798 
VerifyCompute()1799 	virtual long VerifyCompute()
1800 	{
1801 		IVec4* data;
1802 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1803 		if (data[0] != IVec4(1, 5, 9, 13))
1804 		{
1805 			m_context.getTestContext().getLog()
1806 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1807 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1808 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1809 			return ERROR;
1810 		}
1811 		return NO_ERROR;
1812 	}
1813 
Type()1814 	virtual std::string Type()
1815 	{
1816 		return "ivec4";
1817 	}
1818 };
1819 
1820 class PlainGatherUintCube : public GatherBase
1821 {
1822 public:
Init()1823 	virtual void Init()
1824 	{
1825 		CreateTextureCubeInt();
1826 	}
1827 
BufferData()1828 	virtual Vec4 BufferData()
1829 	{
1830 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1831 	}
1832 
Sampler()1833 	virtual std::string Sampler()
1834 	{
1835 		return "uniform usamplerCube my_sampler;                     \n";
1836 	}
1837 
TextBody()1838 	virtual std::string TextBody()
1839 	{
1840 		return Type() + " test_function(vec4 p) {                                \n"
1841 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 0);    \n"
1842 						"}\n";
1843 	}
1844 
InternalFormat()1845 	virtual GLenum InternalFormat()
1846 	{
1847 		return GL_RGBA32UI;
1848 	}
1849 
SetRbo()1850 	virtual void SetRbo()
1851 	{
1852 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
1853 	}
1854 
Verify()1855 	virtual long Verify()
1856 	{
1857 		IVec4 data;
1858 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
1859 		if (data != IVec4(0, 4, 8, 12))
1860 		{
1861 			m_context.getTestContext().getLog()
1862 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
1863 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
1864 			return ERROR;
1865 		}
1866 		return NO_ERROR;
1867 	}
1868 
VerifyCompute()1869 	virtual long VerifyCompute()
1870 	{
1871 		IVec4* data;
1872 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
1873 		if (data[0] != IVec4(0, 4, 8, 12))
1874 		{
1875 			m_context.getTestContext().getLog()
1876 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
1877 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
1878 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
1879 			return ERROR;
1880 		}
1881 		return NO_ERROR;
1882 	}
1883 
Type()1884 	virtual std::string Type()
1885 	{
1886 		return "uvec4";
1887 	}
1888 };
1889 
1890 class PlainGatherDepthCube : public GatherBase
1891 {
1892 public:
Init()1893 	virtual void Init()
1894 	{
1895 		CreateTextureCube();
1896 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1897 	}
1898 
InternalFormat()1899 	virtual GLenum InternalFormat()
1900 	{
1901 		return GL_DEPTH_COMPONENT32F;
1902 	}
1903 
Format()1904 	virtual GLenum Format()
1905 	{
1906 		return GL_DEPTH_COMPONENT;
1907 	}
1908 
BufferData()1909 	virtual Vec4 BufferData()
1910 	{
1911 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
1912 	}
1913 
Sampler()1914 	virtual std::string Sampler()
1915 	{
1916 		return "uniform samplerCubeShadow my_sampler;                     \n";
1917 	}
1918 
TextBody()1919 	virtual std::string TextBody()
1920 	{
1921 		return Type() + " test_function(vec4 p) {                                \n"
1922 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w);  \n"
1923 						"}\n";
1924 	}
1925 
Expected()1926 	virtual Vec4 Expected()
1927 	{
1928 		return Vec4(0, 0, 1, 1);
1929 	}
1930 };
1931 
1932 class PlainGatherFloatCubeArray : public GatherBase
1933 {
1934 public:
Supported()1935 	virtual bool Supported()
1936 	{
1937 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
1938 		{
1939 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
1940 			return false;
1941 		}
1942 		return true;
1943 	}
1944 
Init()1945 	virtual void Init()
1946 	{
1947 		CreateTextureCubeArray(9, 5);
1948 	}
1949 
BufferData()1950 	virtual Vec4 BufferData()
1951 	{
1952 		return Vec4(7. / 16, -10. / 16, 1, 5);
1953 	}
1954 
Sampler()1955 	virtual std::string Sampler()
1956 	{
1957 		return "uniform samplerCubeArray my_sampler;                     \n";
1958 	}
1959 
TextBody()1960 	virtual std::string TextBody()
1961 	{
1962 		return Type() + " test_function(vec4 p) {              \n"
1963 						"    return textureGather(my_sampler, p);       \n"
1964 						"}\n";
1965 	}
1966 };
1967 
1968 class PlainGatherUnormCubeArray : public GatherBase
1969 {
1970 public:
Supported()1971 	virtual bool Supported()
1972 	{
1973 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
1974 		{
1975 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
1976 			return false;
1977 		}
1978 		return true;
1979 	}
1980 
Init()1981 	virtual void Init()
1982 	{
1983 		CreateTextureCubeArray(7, 3);
1984 	}
1985 
BufferData()1986 	virtual Vec4 BufferData()
1987 	{
1988 		return Vec4(7. / 16, -10. / 16, 1, 3);
1989 	}
1990 
Sampler()1991 	virtual std::string Sampler()
1992 	{
1993 		return "uniform samplerCubeArray my_sampler;                     \n";
1994 	}
1995 
TextBody()1996 	virtual std::string TextBody()
1997 	{
1998 		return Type() + " test_function(vec4 p) {              \n"
1999 						"    return textureGather(my_sampler, p);       \n"
2000 						"}\n";
2001 	}
2002 
InternalFormat()2003 	virtual GLenum InternalFormat()
2004 	{
2005 		return GL_RGBA16;
2006 	}
2007 };
2008 
2009 class PlainGatherIntCubeArray : public GatherBase
2010 {
2011 public:
Supported()2012 	virtual bool Supported()
2013 	{
2014 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
2015 		{
2016 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
2017 			return false;
2018 		}
2019 		return true;
2020 	}
2021 
Init()2022 	virtual void Init()
2023 	{
2024 		CreateTextureCubeArrayInt(20, 11);
2025 	}
2026 
BufferData()2027 	virtual Vec4 BufferData()
2028 	{
2029 		return Vec4(7. / 16, -10. / 16, 1, 11);
2030 	}
2031 
Sampler()2032 	virtual std::string Sampler()
2033 	{
2034 		return "uniform isamplerCubeArray my_sampler;                     \n";
2035 	}
2036 
TextBody()2037 	virtual std::string TextBody()
2038 	{
2039 		return Type() + " test_function(vec4 p) {              \n"
2040 						"    return textureGather(my_sampler, p);       \n"
2041 						"}\n";
2042 	}
2043 
InternalFormat()2044 	virtual GLenum InternalFormat()
2045 	{
2046 		return GL_RGBA32I;
2047 	}
2048 
SetRbo()2049 	virtual void SetRbo()
2050 	{
2051 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
2052 	}
2053 
Verify()2054 	virtual long Verify()
2055 	{
2056 		IVec4 data;
2057 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
2058 		if (data != IVec4(0, 4, 8, 12))
2059 		{
2060 			m_context.getTestContext().getLog()
2061 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
2062 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
2063 			return ERROR;
2064 		}
2065 		return NO_ERROR;
2066 	}
2067 
VerifyCompute()2068 	virtual long VerifyCompute()
2069 	{
2070 		IVec4* data;
2071 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2072 		if (data[0] != IVec4(0, 4, 8, 12))
2073 		{
2074 			m_context.getTestContext().getLog()
2075 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
2076 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
2077 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
2078 			return ERROR;
2079 		}
2080 		return NO_ERROR;
2081 	}
2082 
Type()2083 	virtual std::string Type()
2084 	{
2085 		return "ivec4";
2086 	}
2087 };
2088 
2089 class PlainGatherUintCubeArray : public GatherBase
2090 {
2091 public:
Supported()2092 	virtual bool Supported()
2093 	{
2094 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
2095 		{
2096 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
2097 			return false;
2098 		}
2099 		return true;
2100 	}
2101 
Init()2102 	virtual void Init()
2103 	{
2104 		CreateTextureCubeArrayInt(3, 1);
2105 	}
2106 
BufferData()2107 	virtual Vec4 BufferData()
2108 	{
2109 		return Vec4(7. / 16, -10. / 16, 1, 1);
2110 	}
2111 
Sampler()2112 	virtual std::string Sampler()
2113 	{
2114 		return "uniform usamplerCubeArray my_sampler;                     \n";
2115 	}
2116 
TextBody()2117 	virtual std::string TextBody()
2118 	{
2119 		return Type() + " test_function(vec4 p) {              \n"
2120 						"    return textureGather(my_sampler, p);       \n"
2121 						"}\n";
2122 	}
2123 
InternalFormat()2124 	virtual GLenum InternalFormat()
2125 	{
2126 		return GL_RGBA32UI;
2127 	}
2128 
SetRbo()2129 	virtual void SetRbo()
2130 	{
2131 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
2132 	}
2133 
Verify()2134 	virtual long Verify()
2135 	{
2136 		UVec4 data;
2137 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
2138 		if (data != UVec4(0, 4, 8, 12))
2139 		{
2140 			m_context.getTestContext().getLog()
2141 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
2142 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
2143 			return ERROR;
2144 		}
2145 		return NO_ERROR;
2146 	}
2147 
VerifyCompute()2148 	virtual long VerifyCompute()
2149 	{
2150 		IVec4* data;
2151 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2152 		if (data[0] != IVec4(0, 4, 8, 12))
2153 		{
2154 			m_context.getTestContext().getLog()
2155 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
2156 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
2157 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
2158 			return ERROR;
2159 		}
2160 		return NO_ERROR;
2161 	}
2162 
Type()2163 	virtual std::string Type()
2164 	{
2165 		return "uvec4";
2166 	}
2167 };
2168 
2169 class PlainGatherDepthCubeArray : public GatherBase
2170 {
2171 public:
Supported()2172 	virtual bool Supported()
2173 	{
2174 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
2175 		{
2176 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
2177 			return false;
2178 		}
2179 		return true;
2180 	}
2181 
Init()2182 	virtual void Init()
2183 	{
2184 		CreateTextureCubeArray(7, 3);
2185 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
2186 	}
2187 
BufferData()2188 	virtual Vec4 BufferData()
2189 	{
2190 		return Vec4(7. / 16, -10. / 16, 1, 3);
2191 	}
2192 
Sampler()2193 	virtual std::string Sampler()
2194 	{
2195 		return "uniform samplerCubeArrayShadow my_sampler;                     \n";
2196 	}
2197 
TextBody()2198 	virtual std::string TextBody()
2199 	{
2200 		return Type() + " test_function(vec4 p) {                   \n"
2201 						"    return textureGather(my_sampler, p, 7.5/16);    \n"
2202 						"}\n";
2203 	}
2204 
InternalFormat()2205 	virtual GLenum InternalFormat()
2206 	{
2207 		return GL_DEPTH_COMPONENT32F;
2208 	}
2209 
Format()2210 	virtual GLenum Format()
2211 	{
2212 		return GL_DEPTH_COMPONENT;
2213 	}
2214 
Expected()2215 	virtual Vec4 Expected()
2216 	{
2217 		return Vec4(0, 0, 1, 1);
2218 	}
2219 };
2220 
2221 class PlainGatherFloat2DRect : public GatherBase
2222 {
2223 public:
Init()2224 	virtual void Init()
2225 	{
2226 		CreateTexture2D(true);
2227 	}
2228 
BufferData()2229 	virtual Vec4 BufferData()
2230 	{
2231 		return Vec4(23, 26, 0, 0);
2232 	}
2233 
Sampler()2234 	virtual std::string Sampler()
2235 	{
2236 		return "uniform sampler2DRect my_sampler;                     \n";
2237 	}
2238 
Expected()2239 	virtual Vec4 Expected()
2240 	{
2241 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
2242 	}
2243 
TextBody()2244 	virtual std::string TextBody()
2245 	{
2246 		return Type() + " test_function(vec4 p) {                          \n"
2247 						"    return textureGather(my_sampler, vec2(p.x, p.y), 1);   \n"
2248 						"}\n";
2249 	}
2250 };
2251 
2252 class PlainGatherUnorm2DRect : public GatherBase
2253 {
2254 public:
Init()2255 	virtual void Init()
2256 	{
2257 		CreateTexture2D(true);
2258 	}
2259 
BufferData()2260 	virtual Vec4 BufferData()
2261 	{
2262 		return Vec4(23, 26, 0, 0);
2263 	}
2264 
Sampler()2265 	virtual std::string Sampler()
2266 	{
2267 		return "uniform sampler2DRect my_sampler;                     \n";
2268 	}
2269 
TextBody()2270 	virtual std::string TextBody()
2271 	{
2272 		return Type() + " test_function(vec4 p) {                       \n"
2273 						"    return textureGather(my_sampler, vec2(p.x, p.y));   \n"
2274 						"}\n";
2275 	}
2276 
InternalFormat()2277 	virtual GLenum InternalFormat()
2278 	{
2279 		return GL_RGBA16;
2280 	}
2281 };
2282 
2283 class PlainGatherInt2DRect : public GatherBase
2284 {
2285 public:
Init()2286 	virtual void Init()
2287 	{
2288 		CreateTexture2DInt(true);
2289 	}
2290 
BufferData()2291 	virtual Vec4 BufferData()
2292 	{
2293 		return Vec4(22.9f, 25.9f, 0, 0);
2294 	}
2295 
Sampler()2296 	virtual std::string Sampler()
2297 	{
2298 		return "uniform isampler2DRect my_sampler;                     \n";
2299 	}
2300 
TextBody()2301 	virtual std::string TextBody()
2302 	{
2303 		return Type() + " test_function(vec4 p) {                        \n"
2304 						"    return textureGather(my_sampler, vec2(p.x, p.y));    \n"
2305 						"}\n";
2306 	}
2307 
InternalFormat()2308 	virtual GLenum InternalFormat()
2309 	{
2310 		return GL_RGBA32I;
2311 	}
2312 
SetRbo()2313 	virtual void SetRbo()
2314 	{
2315 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
2316 	}
2317 
Verify()2318 	virtual long Verify()
2319 	{
2320 		IVec4 data;
2321 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
2322 		if (data != IVec4(0, 4, 8, 12))
2323 		{
2324 			m_context.getTestContext().getLog()
2325 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
2326 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
2327 			return ERROR;
2328 		}
2329 		return NO_ERROR;
2330 	}
2331 
VerifyCompute()2332 	virtual long VerifyCompute()
2333 	{
2334 		IVec4* data;
2335 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2336 		if (data[0] != IVec4(0, 4, 8, 12))
2337 		{
2338 			m_context.getTestContext().getLog()
2339 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
2340 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
2341 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
2342 			return ERROR;
2343 		}
2344 		return NO_ERROR;
2345 	}
2346 
Type()2347 	virtual std::string Type()
2348 	{
2349 		return "ivec4";
2350 	}
2351 };
2352 
2353 class PlainGatherUint2DRect : public GatherBase
2354 {
2355 public:
Init()2356 	virtual void Init()
2357 	{
2358 		CreateTexture2DInt(true);
2359 	}
2360 
BufferData()2361 	virtual Vec4 BufferData()
2362 	{
2363 		return Vec4(22.9f, 25.9f, 0, 0);
2364 	}
2365 
Sampler()2366 	virtual std::string Sampler()
2367 	{
2368 		return "uniform usampler2DRect my_sampler;                     \n";
2369 	}
2370 
TextBody()2371 	virtual std::string TextBody()
2372 	{
2373 		return Type() + " test_function(vec4 p) {                        \n"
2374 						"    return textureGather(my_sampler, vec2(p.x, p.y));    \n"
2375 						"}\n";
2376 	}
2377 
InternalFormat()2378 	virtual GLenum InternalFormat()
2379 	{
2380 		return GL_RGBA32UI;
2381 	}
2382 
SetRbo()2383 	virtual void SetRbo()
2384 	{
2385 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
2386 	}
2387 
Verify()2388 	virtual long Verify()
2389 	{
2390 		UVec4 data;
2391 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
2392 		if (data != UVec4(0, 4, 8, 12))
2393 		{
2394 			m_context.getTestContext().getLog()
2395 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
2396 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
2397 			return ERROR;
2398 		}
2399 		return NO_ERROR;
2400 	}
2401 
VerifyCompute()2402 	virtual long VerifyCompute()
2403 	{
2404 		IVec4* data;
2405 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
2406 		if (data[0] != IVec4(0, 4, 8, 12))
2407 		{
2408 			m_context.getTestContext().getLog()
2409 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
2410 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
2411 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
2412 			return ERROR;
2413 		}
2414 		return NO_ERROR;
2415 	}
2416 
Type()2417 	virtual std::string Type()
2418 	{
2419 		return "uvec4";
2420 	}
2421 };
2422 
2423 class PlainGatherDepth2DRect : public GatherBase
2424 {
2425 public:
Init()2426 	virtual void Init()
2427 	{
2428 		CreateTexture2D(true);
2429 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
2430 	}
2431 
BufferData()2432 	virtual Vec4 BufferData()
2433 	{
2434 		return Vec4(23, 26, 13.5 / 16, 3);
2435 	}
2436 
Sampler()2437 	virtual std::string Sampler()
2438 	{
2439 		return "uniform sampler2DRectShadow my_sampler;                     \n";
2440 	}
2441 
TextBody()2442 	virtual std::string TextBody()
2443 	{
2444 		return Type() + " test_function(vec4 p) {                             \n"
2445 						"    return textureGather(my_sampler, vec2(p.x, p.y), p.z);    \n"
2446 						"}\n";
2447 	}
2448 
InternalFormat()2449 	virtual GLenum InternalFormat()
2450 	{
2451 		return GL_DEPTH_COMPONENT32F;
2452 	}
2453 
Format()2454 	virtual GLenum Format()
2455 	{
2456 		return GL_DEPTH_COMPONENT;
2457 	}
2458 
Expected()2459 	virtual Vec4 Expected()
2460 	{
2461 		return Vec4(1, 1, 0, 0);
2462 	}
2463 };
2464 
2465 class OffsetGatherFloat2D : public GatherBase
2466 {
BufferData()2467 	virtual Vec4 BufferData()
2468 	{
2469 		return Vec4(19. / 32, 22. / 32, 4, 4);
2470 	}
2471 
TextBody()2472 	virtual std::string TextBody()
2473 	{
2474 		return Type() + " test_function(vec4 p) {                                               \n"
2475 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
2476 						"}\n";
2477 	}
2478 };
2479 
2480 class OffsetGatherUnorm2D : public PlainGatherUnorm2D
2481 {
BufferData()2482 	virtual Vec4 BufferData()
2483 	{
2484 		return Vec4(19. / 32, 22. / 32, 4, 4);
2485 	}
2486 
TestFunction()2487 	virtual std::string TestFunction()
2488 	{
2489 		return "uniform sampler2D my_sampler;                                   \n"
2490 			   ""
2491 			   "vec4 test_function(vec4 p) {                                                    \n"
2492 			   "    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
2493 			   "}\n";
2494 	}
2495 };
2496 
2497 class OffsetGatherInt2D : public PlainGatherInt2DRgba
2498 {
BufferData()2499 	virtual Vec4 BufferData()
2500 	{
2501 		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 4);
2502 	}
2503 
TextBody()2504 	virtual std::string TextBody()
2505 	{
2506 		return Type() + " test_function(vec4 p) {                                               \n"
2507 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
2508 						"}\n";
2509 	}
2510 };
2511 
2512 class OffsetGatherUint2D : public PlainGatherUint2D
2513 {
BufferData()2514 	virtual Vec4 BufferData()
2515 	{
2516 		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 2);
2517 	}
2518 
TextBody()2519 	virtual std::string TextBody()
2520 	{
2521 		return Type() + " test_function(vec4 p) {                                                          \n"
2522 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)), 2);            \n"
2523 						"}\n";
2524 	}
2525 };
2526 
2527 class OffsetGatherDepth2D : public PlainGatherDepth2D
2528 {
BufferData()2529 	virtual Vec4 BufferData()
2530 	{
2531 		return Vec4(19. / 32, 22. / 32, 4, 13.5 / 16);
2532 	}
2533 
TextBody()2534 	virtual std::string TextBody()
2535 	{
2536 		return Type() + " test_function(vec4 p) {                                               \n"
2537 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), p.w, ivec2(int(p.z)));    \n"
2538 						"}\n";
2539 	}
2540 };
2541 
2542 class OffsetGatherFloat2DArray : public PlainGatherFloat2DArray
2543 {
BufferData()2544 	virtual Vec4 BufferData()
2545 	{
2546 		return Vec4(19. / 32, 22. / 32, 5, 4);
2547 	}
2548 
TextBody()2549 	virtual std::string TextBody()
2550 	{
2551 		return Type() + " test_function(vec4 p) {                                                    \n"
2552 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
2553 						"}\n";
2554 	}
2555 };
2556 
2557 class OffsetGatherUnorm2DArray : public PlainGatherUnorm2DArray
2558 {
BufferData()2559 	virtual Vec4 BufferData()
2560 	{
2561 		return Vec4(19. / 32, 22. / 32, 3, 4);
2562 	}
2563 
TextBody()2564 	virtual std::string TextBody()
2565 	{
2566 		return Type() + " test_function(vec4 p) {                                                    \n"
2567 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
2568 						"}\n";
2569 	}
2570 };
2571 
2572 class OffsetGatherInt2DArray : public PlainGatherInt2DArray
2573 {
BufferData()2574 	virtual Vec4 BufferData()
2575 	{
2576 		return Vec4(19. / 32, 22. / 32, 11, 4);
2577 	}
2578 
TextBody()2579 	virtual std::string TextBody()
2580 	{
2581 		return Type() + " test_function(vec4 p) {                                                    \n"
2582 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)), 3); \n"
2583 						"}\n";
2584 	}
2585 };
2586 
2587 class OffsetGatherUint2DArray : public PlainGatherUint2DArray
2588 {
BufferData()2589 	virtual Vec4 BufferData()
2590 	{
2591 		return Vec4(19. / 32, 22. / 32, 1, 4);
2592 	}
2593 
TextBody()2594 	virtual std::string TextBody()
2595 	{
2596 		return Type() + " test_function(vec4 p) {                                                    \n"
2597 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
2598 						"}\n";
2599 	}
2600 };
2601 
2602 class OffsetGatherDepth2DArray : public PlainGatherDepth2DArray
2603 {
Init()2604 	virtual void Init()
2605 	{
2606 		CreateTexture2DArray(7, 3);
2607 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
2608 	}
2609 
BufferData()2610 	virtual Vec4 BufferData()
2611 	{
2612 		return Vec4(19. / 32, 22. / 32, 3, 4);
2613 	}
2614 
TextBody()2615 	virtual std::string TextBody()
2616 	{
2617 		return Type() +
2618 			   " test_function(vec4 p) {                                                                   \n"
2619 			   "    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), p.y + (5./32), ivec2(int(p.w)));    \n"
2620 			   "}\n";
2621 	}
2622 };
2623 
2624 class OffsetGatherFloat2DRect : public PlainGatherFloat2DRect
2625 {
BufferData()2626 	virtual Vec4 BufferData()
2627 	{
2628 		return Vec4(19, 22, 0, 4);
2629 	}
2630 
TextBody()2631 	virtual std::string TextBody()
2632 	{
2633 		return Type() + " test_function(vec4 p) {                                                  \n"
2634 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)), 1);    \n"
2635 						"}\n";
2636 	}
2637 };
2638 
2639 class OffsetGatherUnorm2DRect : public PlainGatherUnorm2DRect
2640 {
BufferData()2641 	virtual Vec4 BufferData()
2642 	{
2643 		return Vec4(30.9f, 18.9f, -8.f, 7.f);
2644 	}
2645 
TextBody()2646 	virtual std::string TextBody()
2647 	{
2648 		return Type() + " test_function(vec4 p) {                                                         \n"
2649 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z), int(p.w)));    \n"
2650 						"}\n";
2651 	}
2652 };
2653 
2654 class OffsetGatherInt2DRect : public PlainGatherInt2DRect
2655 {
BufferData()2656 	virtual Vec4 BufferData()
2657 	{
2658 		return Vec4(22.9f, 25.9f, 0, 0);
2659 	}
2660 
TextBody()2661 	virtual std::string TextBody()
2662 	{
2663 		return Type() + " test_function(vec4 p) {                                               \n"
2664 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)));    \n"
2665 						"}\n";
2666 	}
2667 };
2668 
2669 class OffsetGatherUint2DRect : public PlainGatherUint2DRect
2670 {
BufferData()2671 	virtual Vec4 BufferData()
2672 	{
2673 		return Vec4(26.9f, 29.9f, 0, -4);
2674 	}
2675 
TextBody()2676 	virtual std::string TextBody()
2677 	{
2678 		return Type() + " test_function(vec4 p) {                                               \n"
2679 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)));    \n"
2680 						"}\n";
2681 	}
2682 };
2683 
2684 class OffsetGatherDepth2DRect : public PlainGatherDepth2DRect
2685 {
BufferData()2686 	virtual Vec4 BufferData()
2687 	{
2688 		return Vec4(19, 22, 13.5 / 16, 4);
2689 	}
2690 
TextBody()2691 	virtual std::string TextBody()
2692 	{
2693 		return Type() + " test_function(vec4 p) {                                                    \n"
2694 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), p.z, ivec2(int(p.w)));    \n"
2695 						"}\n";
2696 	}
2697 };
2698 
2699 class OffsetsGatherFloat2D : public OffsetGatherFloat2D
2700 {
BufferData()2701 	virtual Vec4 BufferData()
2702 	{
2703 		return Vec4(18. / 32, 8. / 32, 0, 0);
2704 	}
2705 
TextBody()2706 	virtual std::string TextBody()
2707 	{
2708 		return Type() +
2709 			   " test_function(vec4 p) {                                                             \n"
2710 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2711 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2712 			   "}\n";
2713 	}
2714 };
2715 
2716 class OffsetsGatherUnorm2D : public OffsetGatherUnorm2D
2717 {
BufferData()2718 	virtual Vec4 BufferData()
2719 	{
2720 		return Vec4(18. / 32, 8. / 32, 0, 0);
2721 	}
2722 
TestFunction()2723 	virtual std::string TestFunction()
2724 	{
2725 		return "uniform sampler2D my_sampler;                                   \n"
2726 			   ""
2727 			   "vec4  test_function(vec4 p) {                                                             \n"
2728 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2729 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2730 			   "}\n";
2731 	}
2732 };
2733 
2734 class OffsetsGatherInt2D : public OffsetGatherInt2D
2735 {
BufferData()2736 	virtual Vec4 BufferData()
2737 	{
2738 		return Vec4(18. / 32, 8. / 32, 0, 0);
2739 	}
2740 
TextBody()2741 	virtual std::string TextBody()
2742 	{
2743 		return Type() +
2744 			   " test_function(vec4 p) {                                                             \n"
2745 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2746 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2747 			   "}\n";
2748 	}
2749 };
2750 
2751 class OffsetsGatherUint2D : public OffsetGatherUint2D
2752 {
BufferData()2753 	virtual Vec4 BufferData()
2754 	{
2755 		return Vec4(18. / 32, 8. / 32, 2, 2);
2756 	}
2757 
TextBody()2758 	virtual std::string TextBody()
2759 	{
2760 		return Type() +
2761 			   " test_function(vec4 p) {                                                             \n"
2762 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2763 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets, 2);                      \n"
2764 			   "}\n";
2765 	}
2766 };
2767 
2768 class OffsetsGatherDepth2D : public OffsetGatherDepth2D
2769 {
BufferData()2770 	virtual Vec4 BufferData()
2771 	{
2772 		return Vec4(18. / 32, 8. / 32, 0.49f, 0);
2773 	}
2774 
TextBody()2775 	virtual std::string TextBody()
2776 	{
2777 		return Type() +
2778 			   " test_function(vec4 p) {                                                             \n"
2779 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2780 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), p.z, offsets);                    \n"
2781 			   "}\n";
2782 	}
2783 
Expected()2784 	virtual Vec4 Expected()
2785 	{
2786 		return Vec4(0, 0, 1, 1);
2787 	}
2788 };
2789 
2790 class OffsetsGatherFloat2DArray : public PlainGatherFloat2DArray
2791 {
Init()2792 	virtual void Init()
2793 	{
2794 		CreateTexture2DArray(3, 1);
2795 	}
2796 
BufferData()2797 	virtual Vec4 BufferData()
2798 	{
2799 		return Vec4(18. / 32, 8. / 32, 1, 0);
2800 	}
2801 
TextBody()2802 	virtual std::string TextBody()
2803 	{
2804 		return Type() +
2805 			   " test_function(vec4 p) {                                                             \n"
2806 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2807 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
2808 			   "}\n";
2809 	}
2810 };
2811 
2812 class OffsetsGatherUnorm2DArray : public PlainGatherUnorm2DArray
2813 {
Init()2814 	virtual void Init()
2815 	{
2816 		CreateTexture2DArray(3, 1);
2817 	}
2818 
BufferData()2819 	virtual Vec4 BufferData()
2820 	{
2821 		return Vec4(18. / 32, 8. / 32, 1, 0);
2822 	}
2823 
TextBody()2824 	virtual std::string TextBody()
2825 	{
2826 		return Type() +
2827 			   " test_function(vec4 p) {                                                             \n"
2828 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2829 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
2830 			   "}\n";
2831 	}
2832 };
2833 
2834 class OffsetsGatherInt2DArray : public PlainGatherInt2DArray
2835 {
Init()2836 	virtual void Init()
2837 	{
2838 		CreateTexture2DArrayInt(3, 1);
2839 	}
2840 
BufferData()2841 	virtual Vec4 BufferData()
2842 	{
2843 		return Vec4(18. / 32, 8. / 32, 1, 0);
2844 	}
2845 
TextBody()2846 	virtual std::string TextBody()
2847 	{
2848 		return Type() +
2849 			   " test_function(vec4 p) {                                                             \n"
2850 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2851 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets, 3);                 \n"
2852 			   "}\n";
2853 	}
2854 };
2855 
2856 class OffsetsGatherUint2DArray : public PlainGatherUint2DArray
2857 {
Init()2858 	virtual void Init()
2859 	{
2860 		CreateTexture2DArrayInt(3, 1);
2861 	}
2862 
BufferData()2863 	virtual Vec4 BufferData()
2864 	{
2865 		return Vec4(18. / 32, 8. / 32, 1, 0);
2866 	}
2867 
TextBody()2868 	virtual std::string TextBody()
2869 	{
2870 		return Type() +
2871 			   " test_function(vec4 p) {                                                             \n"
2872 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2873 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
2874 			   "}\n";
2875 	}
2876 };
2877 
2878 class OffsetsGatherDepth2DArray : public PlainGatherDepth2DArray
2879 {
Init()2880 	virtual void Init()
2881 	{
2882 		CreateTexture2DArray(3, 1);
2883 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
2884 	}
2885 
BufferData()2886 	virtual Vec4 BufferData()
2887 	{
2888 		return Vec4(18. / 32, 8. / 32, 1, 0.49f);
2889 	}
2890 
TextBody()2891 	virtual std::string TextBody()
2892 	{
2893 		return Type() +
2894 			   " test_function(vec4 p) {                                                             \n"
2895 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2896 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), p.w, offsets);               \n"
2897 			   "}\n";
2898 	}
2899 
Expected()2900 	virtual Vec4 Expected()
2901 	{
2902 		return Vec4(0, 0, 1, 1);
2903 	}
2904 };
2905 
2906 class OffsetsGatherFloat2DRect : public PlainGatherFloat2DRect
2907 {
BufferData()2908 	virtual Vec4 BufferData()
2909 	{
2910 		return Vec4(18, 8, 0, 0);
2911 	}
2912 
TextBody()2913 	virtual std::string TextBody()
2914 	{
2915 		return Type() +
2916 			   " test_function(vec4 p) {                                                             \n"
2917 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2918 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets, 1);                      \n"
2919 			   "}\n";
2920 	}
2921 };
2922 
2923 class OffsetsGatherUnorm2DRect : public PlainGatherUnorm2DRect
2924 {
BufferData()2925 	virtual Vec4 BufferData()
2926 	{
2927 		return Vec4(18, 8, 0, 0);
2928 	}
2929 
TextBody()2930 	virtual std::string TextBody()
2931 	{
2932 		return Type() +
2933 			   " test_function(vec4 p) {                                                             \n"
2934 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2935 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2936 			   "}\n";
2937 	}
2938 };
2939 
2940 class OffsetsGatherInt2DRect : public PlainGatherUint2DRect
2941 {
BufferData()2942 	virtual Vec4 BufferData()
2943 	{
2944 		return Vec4(17.9f, 7.9f, 0, 0);
2945 	}
2946 
TextBody()2947 	virtual std::string TextBody()
2948 	{
2949 		return Type() +
2950 			   " test_function(vec4 p) {                                                             \n"
2951 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2952 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2953 			   "}\n";
2954 	}
2955 };
2956 
2957 class OffsetsGatherUint2DRect : public PlainGatherUint2DRect
2958 {
BufferData()2959 	virtual Vec4 BufferData()
2960 	{
2961 		return Vec4(17.9f, 7.9f, 0, 0);
2962 	}
2963 
TextBody()2964 	virtual std::string TextBody()
2965 	{
2966 		return Type() +
2967 			   " test_function(vec4 p) {                                                             \n"
2968 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2969 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
2970 			   "}\n";
2971 	}
2972 };
2973 
2974 class OffsetsGatherDepth2DRect : public PlainGatherDepth2DRect
2975 {
BufferData()2976 	virtual Vec4 BufferData()
2977 	{
2978 		return Vec4(17.9f, 7.9f, 0.49f, 0);
2979 	}
2980 
TextBody()2981 	virtual std::string TextBody()
2982 	{
2983 		return Type() +
2984 			   " test_function(vec4 p) {                                                             \n"
2985 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
2986 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), p.z, offsets);                    \n"
2987 			   "}\n";
2988 	}
2989 
Expected()2990 	virtual Vec4 Expected()
2991 	{
2992 		return Vec4(0, 0, 1, 1);
2993 	}
2994 };
2995 
2996 class Swizzle : public PlainGatherFloat2DRgba
2997 {
TestFunction()2998 	virtual std::string TestFunction()
2999 	{
3000 		return "uniform sampler2D my_sampler;                                   \n"
3001 			   ""
3002 			   "vec4 test_function(vec4 p) {                                    \n"
3003 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 1).yzww;   \n"
3004 			   "}\n";
3005 	}
3006 
Expected()3007 	virtual Vec4 Expected()
3008 	{
3009 		return Vec4(5. / 16, 9. / 16, 13. / 16, 13. / 16);
3010 	}
3011 };
3012 
3013 class BaseLevel : public PlainGatherFloat2DRgba
3014 {
Init()3015 	virtual void Init()
3016 	{
3017 		CreateTexture2D(false, true);
3018 	}
3019 };
3020 
3021 class IncompleteTexture : public PlainGatherFloat2DRgba
3022 {
Init()3023 	virtual void Init()
3024 	{
3025 		CreateTexture2D();
3026 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
3027 	}
3028 
Expected()3029 	virtual Vec4 Expected()
3030 	{
3031 		return Vec4(0);
3032 	}
3033 };
3034 
3035 class IncompleteTextureLastComp : public PlainGatherFloat2DRgba
3036 {
Init()3037 	virtual void Init()
3038 	{
3039 		CreateTexture2D();
3040 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
3041 	}
3042 
Expected()3043 	virtual Vec4 Expected()
3044 	{
3045 		return Vec4(1);
3046 	}
3047 
TestFunction()3048 	virtual std::string TestFunction()
3049 	{
3050 		return "uniform sampler2D my_sampler;                                   \n"
3051 			   ""
3052 			   "vec4 test_function(vec4 p) {                                    \n"
3053 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 3);        \n"
3054 			   "}\n";
3055 	}
3056 };
3057 
3058 class TriangleDraw : public GatherBase
3059 {
3060 	GLuint program, rbo, fbo, vao, vbo;
3061 
VertexShader()3062 	virtual std::string VertexShader()
3063 	{
3064 		return "#version 400                                  \n"
3065 			   "out vec2 texcoords;                           \n"
3066 			   "in vec4 Vertex;                               \n"
3067 			   "void main() {                                 \n"
3068 			   "   gl_Position = Vertex;                      \n"
3069 			   "   texcoords = (Vertex.xy + vec2(1.0)) / 2.0; \n"
3070 			   "}\n";
3071 	}
3072 
FragmentShader()3073 	virtual std::string FragmentShader()
3074 	{
3075 		return "#version 400                                      \n"
3076 			   "in vec2 texcoords;                                \n"
3077 			   "out vec4 FragColor;                               \n"
3078 			   "uniform sampler2D tex;                            \n"
3079 			   "void main() {                                     \n"
3080 			   "   FragColor = textureGather(tex, texcoords, 2);  \n"
3081 			   "}\n";
3082 	}
3083 
Run()3084 	virtual long Run()
3085 	{
3086 		glGenFramebuffers(1, &fbo);
3087 		glGenRenderbuffers(1, &rbo);
3088 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
3089 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 100, 100);
3090 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3091 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
3092 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
3093 		glDrawBuffers(1, &drawBuffer);
3094 		GLfloat colorf[4] = { 0, 0, 0, 0 };
3095 		glClearBufferfv(GL_COLOR, 0, colorf);
3096 		glViewport(0, 0, 100, 100);
3097 
3098 		program = CreateProgram(VertexShader().c_str(), NULL, NULL, NULL, FragmentShader().c_str());
3099 		glBindAttribLocation(program, 0, "Vertex");
3100 		glBindFragDataLocation(program, 0, "FragColor");
3101 		glLinkProgram(program);
3102 		if (!CheckProgram(program))
3103 			return ERROR;
3104 		glUseProgram(program);
3105 
3106 		glGenTextures(1, &tex);
3107 		glBindTexture(GL_TEXTURE_2D, tex);
3108 		std::vector<Vec4> data(100 * 100, Vec4(0.25, 0.5, 0.75, 1));
3109 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, &data[0]);
3110 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3111 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3112 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3113 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3114 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3115 
3116 		GLuint l_vao;
3117 		glGenVertexArrays(1, &l_vao);
3118 		glBindVertexArray(l_vao);
3119 		glGenBuffers(1, &vbo);
3120 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
3121 		GLfloat buffData[16] = { -1, 1, 0, 1, -1, -1, 0, 1, 1, 1, 0, 1, 1, -1, 0, 1 };
3122 		glBufferData(GL_ARRAY_BUFFER, sizeof(buffData), buffData, GL_STATIC_DRAW);
3123 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
3124 		glEnableVertexAttribArray(0);
3125 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
3126 		glDisableVertexAttribArray(0);
3127 		glDeleteVertexArrays(1, &l_vao);
3128 		glBindBuffer(GL_ARRAY_BUFFER, 0);
3129 
3130 		glReadBuffer(GL_COLOR_ATTACHMENT0);
3131 		std::vector<Vec4> read(100 * 100, Vec4(0));
3132 		glReadPixels(0, 0, 100, 100, GL_RGBA, GL_FLOAT, &read[0]);
3133 		for (unsigned int i = 0; i < read.size(); ++i)
3134 		{
3135 			if (read[i] != Vec4(0.75))
3136 			{
3137 				m_context.getTestContext().getLog()
3138 					<< tcu::TestLog::Message << "Got: " << read[i].x() << " " << read[i].y() << " " << read[i].z()
3139 					<< " " << read[i].w() << ", expected vec4(0.25)" << tcu::TestLog::EndMessage;
3140 				return ERROR;
3141 			}
3142 		}
3143 
3144 		return NO_ERROR;
3145 	}
3146 
Cleanup()3147 	virtual long Cleanup()
3148 	{
3149 		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
3150 		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
3151 		glDeleteTextures(1, &tex);
3152 		glDeleteFramebuffers(1, &fbo);
3153 		glDeleteRenderbuffers(1, &rbo);
3154 		glDeleteVertexArrays(1, &vao);
3155 		glDeleteBuffers(1, &vbo);
3156 		glDeleteProgram(program);
3157 		return NO_ERROR;
3158 	}
3159 };
3160 
3161 class PlainGatherFloat2DSrgb : public GatherBase
3162 {
3163 public:
Expected()3164 	virtual Vec4 Expected()
3165 	{
3166 		return Vec4(0.f, 0.0512695f, 0.21582f, 0.519531f);
3167 	}
3168 
InternalFormat()3169 	virtual GLenum InternalFormat()
3170 	{
3171 		return GL_SRGB8_ALPHA8;
3172 	}
3173 };
3174 
3175 class PlainGatherFloat2DSrgbAlpha : public GatherBase
3176 {
3177 public:
TestFunction()3178 	virtual std::string TestFunction()
3179 	{
3180 		return "uniform sampler2D my_sampler;                                   \n"
3181 			   ""
3182 			   "vec4 test_function(vec4 p) {                                    \n"
3183 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 3);        \n"
3184 			   "}\n";
3185 	}
3186 
Expected()3187 	virtual Vec4 Expected()
3188 	{
3189 		return Vec4(3. / 16, 7. / 16, 11. / 16, 15. / 16);
3190 	}
3191 
InternalFormat()3192 	virtual GLenum InternalFormat()
3193 	{
3194 		return GL_SRGB8_ALPHA8;
3195 	}
3196 };
3197 
3198 class GatherGeometryShader : public GatherBase
3199 {
VertexShader()3200 	virtual std::string VertexShader()
3201 	{
3202 		return "#version 400                       \n"
3203 			   "in vec4 v_in_0;                    \n"
3204 			   "out vec4 d;                        \n"
3205 			   "void main() {                      \n"
3206 			   "   gl_Position = vec4(0, 0, 0, 1); \n"
3207 			   "   d = v_in_0;                     \n"
3208 			   "}";
3209 	}
3210 
GeometryShader()3211 	virtual std::string GeometryShader()
3212 	{
3213 		return "#version 400                                                  \n"
3214 			   "layout(points) in;                                            \n"
3215 			   "layout(points, max_vertices = 1) out;                         \n"
3216 			   "out vec4 col;                                                 \n"
3217 			   "in vec4 d[1];                                                 \n"
3218 			   "uniform sampler2D tex;                                        \n"
3219 			   ""
3220 			   "void main() {                                                 \n"
3221 			   "   vec4 v1 = textureGather(tex, vec2(d[0].x, d[0].y));                                               \n"
3222 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d[0].x, d[0].y) - vec2(4./32), ivec2(4));                 \n"
3223 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));         \n"
3224 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d[0].x, d[0].y) - vec2(5./32, 18./32), offsets);         \n"
3225 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                \n"
3226 			   "   float error = 0.0;                                         \n"
3227 			   ""
3228 			   "   if (v1 != expected)    \n"
3229 			   "       error += 0.01;     \n"
3230 			   "   if (v2 != expected)    \n"
3231 			   "       error += 0.02;     \n"
3232 			   "   if (v3 != expected)    \n"
3233 			   "       error += 0.04;     \n"
3234 			   ""
3235 			   "   if (error != 0.0)                         \n"
3236 			   "       col = vec4(v1.x, v2.y, v3.z, d[0].x); \n"
3237 			   "   else                                      \n"
3238 			   "       col = vec4(0, 1, 0, 1);               \n"
3239 			   ""
3240 			   "   gl_Position = vec4(0, 0, 0, 1);         \n"
3241 			   "   EmitVertex();                           \n"
3242 			   "   EndPrimitive();                         \n"
3243 			   "}";
3244 	}
3245 
FragmentShader()3246 	virtual std::string FragmentShader()
3247 	{
3248 		return "#version 400               \n"
3249 			   "in vec4 col;               \n"
3250 			   "out vec4 f_out_0;          \n"
3251 			   "void main() {              \n"
3252 			   "   f_out_0 = col;          \n"
3253 			   "}";
3254 	}
3255 
Run()3256 	virtual long Run()
3257 	{
3258 		if (!Supported())
3259 			return NO_ERROR;
3260 		Init();
3261 
3262 		glGenFramebuffers(1, &fbo);
3263 		glGenRenderbuffers(1, &rbo);
3264 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
3265 		SetRbo();
3266 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3267 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
3268 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
3269 		glDrawBuffers(1, &drawBuffer);
3270 		GLfloat colorf[4] = { 0, 0, 0, 0 };
3271 		glClearBufferfv(GL_COLOR, 0, colorf);
3272 		glViewport(0, 0, 1, 1);
3273 
3274 		glGenVertexArrays(1, &vao);
3275 		glBindVertexArray(vao);
3276 		glGenBuffers(1, &vbo);
3277 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
3278 		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
3279 		glEnableVertexAttribArray(0);
3280 		Vec4 buffData = BufferData();
3281 		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
3282 
3283 		program = CreateProgram(VertexShader().c_str(), NULL, NULL, GeometryShader().c_str(), FragmentShader().c_str());
3284 		glBindAttribLocation(program, 0, "v_in_0");
3285 		glBindFragDataLocation(program, 0, "f_out_0");
3286 		glLinkProgram(program);
3287 		if (!CheckProgram(program))
3288 			return ERROR;
3289 		glUseProgram(program);
3290 
3291 		glDrawArrays(GL_POINTS, 0, 1);
3292 		glReadBuffer(GL_COLOR_ATTACHMENT0);
3293 
3294 		glDeleteProgram(program);
3295 		Vec4 data;
3296 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, &data);
3297 		if (!ColorEqual(data, Vec4(0, 1, 0, 1), g_color_eps))
3298 		{
3299 			m_context.getTestContext().getLog()
3300 				<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data.x() << ", " << data.y() << ", "
3301 				<< data.z() << ", " << data.w() << ", epsilon: " << g_color_eps.x() << ", " << g_color_eps.y() << ", "
3302 				<< g_color_eps.z() << ", " << g_color_eps.w() << tcu::TestLog::EndMessage;
3303 			return ERROR;
3304 		}
3305 		return NO_ERROR;
3306 	}
3307 };
3308 
3309 class GatherTesselationShader : public GatherBase
3310 {
VertexShader()3311 	virtual std::string VertexShader()
3312 	{
3313 		return "#version 400               \n"
3314 			   "in vec4 v_in_0;            \n"
3315 			   "out vec4 d;                \n"
3316 			   "void main() {              \n"
3317 			   "   gl_Position = vec4(0, 0, 0, 1); \n"
3318 			   "   d = v_in_0;             \n"
3319 			   "}";
3320 	}
3321 
ControlShader()3322 	virtual std::string ControlShader()
3323 	{
3324 		return "#version 400                                                  \n"
3325 			   "layout(vertices = 1) out;                                     \n"
3326 			   "out vec4 ccol[];                                              \n"
3327 			   "in vec4 d[];                                                  \n"
3328 			   "out vec4 d_con[];                                             \n"
3329 			   "uniform sampler2D tex;                                        \n"
3330 			   ""
3331 			   "void main() {                                        \n"
3332 			   "   vec4 v1 = textureGather(tex, vec2(d[0].x, d[0].y));                                               \n"
3333 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d[0].x, d[0].y) - vec2(4./32), ivec2(4));                 \n"
3334 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));         \n"
3335 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d[0].x, d[0].y) - vec2(5./32, 18./32), offsets);         \n"
3336 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                \n"
3337 			   "   float error = 0.0;                                         \n"
3338 			   ""
3339 			   "   if (v1 != expected)    \n"
3340 			   "       error += 0.01;     \n"
3341 			   "   if (v2 != expected)    \n"
3342 			   "       error += 0.02;     \n"
3343 			   "   if (v3 != expected)    \n"
3344 			   "       error += 0.04;     \n"
3345 			   ""
3346 			   "   if (error != 0.0)                                            \n"
3347 			   "       ccol[gl_InvocationID] = vec4(v1.x, v2.y, d[0].x, 1);      \n"
3348 			   "   else                                                         \n"
3349 			   "       ccol[gl_InvocationID] = vec4(0, 1, 0, 1);                \n"
3350 			   ""
3351 			   "   d_con[gl_InvocationID] = d[gl_InvocationID];                                 \n"
3352 			   "   gl_out[gl_InvocationID].gl_Position = vec4(0, 0, 0, 1);                      \n"
3353 			   "   gl_TessLevelInner[0] = 1.0;                                                  \n"
3354 			   "   gl_TessLevelOuter[0] = 1.0;                                                  \n"
3355 			   "   gl_TessLevelOuter[1] = 1.0;                                                  \n"
3356 			   "   gl_TessLevelOuter[2] = 1.0;                                                  \n"
3357 			   "}";
3358 	}
3359 
EvalShader()3360 	virtual std::string EvalShader()
3361 	{
3362 		return "#version 400                                                  \n"
3363 			   "layout(triangles, point_mode) in;                             \n"
3364 			   "in vec4 ccol[];                                               \n"
3365 			   "in vec4 d_con[];                                              \n"
3366 			   "out vec4 ecol;                                                \n"
3367 			   "uniform sampler2D tex;                                        \n"
3368 			   ""
3369 			   "void main() {                                        \n"
3370 			   "   vec4 v1 = textureGather(tex, vec2(d_con[0].x, d_con[0].y));                                         "
3371 			   "      \n"
3372 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d_con[0].x, d_con[0].y) - vec2(4./32), ivec2(4));           "
3373 			   "      \n"
3374 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));           "
3375 			   "      \n"
3376 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d_con[0].x, d_con[0].y) - vec2(5./32, 18./32), offsets);   "
3377 			   "      \n"
3378 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                  "
3379 			   "      \n"
3380 			   "   float error = 0.0;                                         \n"
3381 			   ""
3382 			   "   if (v1 != expected)    \n"
3383 			   "       error += 0.01;     \n"
3384 			   "   if (v2 != expected)    \n"
3385 			   "       error += 0.02;     \n"
3386 			   "   if (v3 != expected)    \n"
3387 			   "       error += 0.04;     \n"
3388 			   ""
3389 			   "   if (error != 0.0)                                          \n"
3390 			   "       ecol = vec4(v1.x, v2.y, d_con[0].x, -1);                      \n"
3391 			   "   else if (ccol[0] != vec4(0, 1, 0, 1))     \n"
3392 			   "       ecol = ccol[0];                       \n"
3393 			   "   else                                      \n"
3394 			   "       ecol = vec4(0, 1, 0, 1);              \n"
3395 			   ""
3396 			   "   gl_Position = vec4(0, 0, 0, 1);   \n"
3397 			   "}";
3398 	}
3399 
FragmentShader()3400 	virtual std::string FragmentShader()
3401 	{
3402 		return "#version 400               \n"
3403 			   "in vec4 ecol;              \n"
3404 			   "out vec4 f_out_0;          \n"
3405 			   "void main() {              \n"
3406 			   "   f_out_0 = ecol;         \n"
3407 			   "}";
3408 	}
3409 
Run()3410 	virtual long Run()
3411 	{
3412 
3413 		if (!Supported())
3414 			return NO_ERROR;
3415 		Init();
3416 
3417 		glGenFramebuffers(1, &fbo);
3418 		glGenRenderbuffers(1, &rbo);
3419 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
3420 		SetRbo();
3421 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3422 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
3423 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
3424 		glDrawBuffers(1, &drawBuffer);
3425 		GLfloat colorf[4] = { 0, 0, 0, 0 };
3426 		glClearBufferfv(GL_COLOR, 0, colorf);
3427 		glViewport(0, 0, 1, 1);
3428 
3429 		glGenVertexArrays(1, &vao);
3430 		glBindVertexArray(vao);
3431 		glGenBuffers(1, &vbo);
3432 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
3433 		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
3434 		glEnableVertexAttribArray(0);
3435 		Vec4 buffData = BufferData();
3436 		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
3437 
3438 		program = CreateProgram(VertexShader().c_str(), ControlShader().c_str(), EvalShader().c_str(), NULL,
3439 								FragmentShader().c_str());
3440 		glBindAttribLocation(program, 0, "v_in_0");
3441 		glBindFragDataLocation(program, 0, "f_out_0");
3442 		glLinkProgram(program);
3443 		if (!CheckProgram(program))
3444 			return ERROR;
3445 		glUseProgram(program);
3446 
3447 		glPatchParameteri(GL_PATCH_VERTICES, 1);
3448 		glDrawArrays(GL_PATCHES, 0, 1);
3449 		glReadBuffer(GL_COLOR_ATTACHMENT0);
3450 
3451 		glDeleteProgram(program);
3452 		Vec4 data;
3453 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, &data);
3454 		if (!ColorEqual(data, Vec4(0, 1, 0, 1), g_color_eps))
3455 		{
3456 			m_context.getTestContext().getLog()
3457 				<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data.x() << ", " << data.y() << ", "
3458 				<< data.z() << ", " << data.w() << ", epsilon: " << g_color_eps.x() << ", " << g_color_eps.y() << ", "
3459 				<< g_color_eps.z() << ", " << g_color_eps.w() << tcu::TestLog::EndMessage;
3460 			return ERROR;
3461 		}
3462 		return NO_ERROR;
3463 	}
3464 };
3465 
3466 class PlainGatherFloat2DRgb : public GatherBase
3467 {
3468 public:
Init()3469 	virtual void Init()
3470 	{
3471 		CreateTexture2DRgb();
3472 	}
3473 };
3474 
3475 class PlainGatherFloat2DR : public GatherBase
3476 {
3477 public:
Init()3478 	virtual void Init()
3479 	{
3480 		CreateTexture2DR();
3481 	}
3482 };
3483 
3484 class OffsetGatherFloat2DRgb : public OffsetGatherFloat2D
3485 {
3486 public:
Init()3487 	virtual void Init()
3488 	{
3489 		CreateTexture2DRgb();
3490 	}
3491 };
3492 
3493 class OffsetGatherFloat2DRg : public OffsetGatherFloat2D
3494 {
3495 public:
Init()3496 	virtual void Init()
3497 	{
3498 		CreateTexture2DRg();
3499 	}
3500 };
3501 
3502 class OffsetGatherFloat2DR : public OffsetGatherFloat2D
3503 {
3504 public:
Init()3505 	virtual void Init()
3506 	{
3507 		CreateTexture2DR();
3508 	}
3509 };
3510 
3511 } // anonymous namespace
3512 
TextureGatherTests(deqp::Context & context)3513 TextureGatherTests::TextureGatherTests(deqp::Context& context) : TestCaseGroup(context, "texture_gather", "")
3514 {
3515 }
3516 
~TextureGatherTests(void)3517 TextureGatherTests::~TextureGatherTests(void)
3518 {
3519 }
3520 
init()3521 void TextureGatherTests::init()
3522 {
3523 	using namespace deqp;
3524 	addChild(new TestSubcase(m_context, "api-enums", TestSubcase::Create<GatherEnumsTest>));
3525 	addChild(new TestSubcase(m_context, "gather-glsl-compile", TestSubcase::Create<GatherGLSLCompile>));
3526 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgba", TestSubcase::Create<PlainGatherFloat2DRgba>));
3527 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rg", TestSubcase::Create<PlainGatherFloat2DRg>));
3528 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2d", TestSubcase::Create<PlainGatherUnorm2D>));
3529 	addChild(new TestSubcase(m_context, "plain-gather-int-2d-rgba", TestSubcase::Create<PlainGatherInt2DRgba>));
3530 	addChild(new TestSubcase(m_context, "plain-gather-int-2d-rg", TestSubcase::Create<PlainGatherInt2DRg>));
3531 	addChild(new TestSubcase(m_context, "plain-gather-uint-2d", TestSubcase::Create<PlainGatherUint2D>));
3532 	addChild(new TestSubcase(m_context, "plain-gather-depth-2d", TestSubcase::Create<PlainGatherDepth2D>));
3533 	addChild(new TestSubcase(m_context, "plain-gather-float-2darray", TestSubcase::Create<PlainGatherFloat2DArray>));
3534 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2darray", TestSubcase::Create<PlainGatherUnorm2DArray>));
3535 	addChild(new TestSubcase(m_context, "plain-gather-int-2darray", TestSubcase::Create<PlainGatherInt2DArray>));
3536 	addChild(new TestSubcase(m_context, "plain-gather-uint-2darray", TestSubcase::Create<PlainGatherUint2DArray>));
3537 	addChild(new TestSubcase(m_context, "plain-gather-depth-2darray", TestSubcase::Create<PlainGatherDepth2DArray>));
3538 	addChild(new TestSubcase(m_context, "plain-gather-float-cube-rgba", TestSubcase::Create<PlainGatherFloatCubeRgba>));
3539 	addChild(new TestSubcase(m_context, "plain-gather-float-cube-rg", TestSubcase::Create<PlainGatherFloatCubeRg>));
3540 	addChild(new TestSubcase(m_context, "plain-gather-unorm-cube", TestSubcase::Create<PlainGatherUnormCube>));
3541 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-rgba", TestSubcase::Create<PlainGatherIntCubeRgba>));
3542 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-rg", TestSubcase::Create<PlainGatherIntCubeRg>));
3543 	addChild(new TestSubcase(m_context, "plain-gather-uint-cube", TestSubcase::Create<PlainGatherUintCube>));
3544 	addChild(new TestSubcase(m_context, "plain-gather-depth-cube", TestSubcase::Create<PlainGatherDepthCube>));
3545 	addChild(
3546 		new TestSubcase(m_context, "plain-gather-float-cube-array", TestSubcase::Create<PlainGatherFloatCubeArray>));
3547 	addChild(
3548 		new TestSubcase(m_context, "plain-gather-unorm-cube-array", TestSubcase::Create<PlainGatherUnormCubeArray>));
3549 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-array", TestSubcase::Create<PlainGatherIntCubeArray>));
3550 	addChild(new TestSubcase(m_context, "plain-gather-uint-cube-array", TestSubcase::Create<PlainGatherUintCubeArray>));
3551 	addChild(
3552 		new TestSubcase(m_context, "plain-gather-depth-cube-array", TestSubcase::Create<PlainGatherDepthCubeArray>));
3553 	addChild(new TestSubcase(m_context, "plain-gather-float-2drect", TestSubcase::Create<PlainGatherFloat2DRect>));
3554 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2drect", TestSubcase::Create<PlainGatherUnorm2DRect>));
3555 	addChild(new TestSubcase(m_context, "plain-gather-int-2drect", TestSubcase::Create<PlainGatherInt2DRect>));
3556 	addChild(new TestSubcase(m_context, "plain-gather-uint-2drect", TestSubcase::Create<PlainGatherUint2DRect>));
3557 	addChild(new TestSubcase(m_context, "plain-gather-depth-2drect", TestSubcase::Create<PlainGatherDepth2DRect>));
3558 	addChild(new TestSubcase(m_context, "offset-gather-float-2d", TestSubcase::Create<OffsetGatherFloat2D>));
3559 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2d", TestSubcase::Create<OffsetGatherUnorm2D>));
3560 	addChild(new TestSubcase(m_context, "offset-gather-int-2d", TestSubcase::Create<OffsetGatherInt2D>));
3561 	addChild(new TestSubcase(m_context, "offset-gather-uint-2d", TestSubcase::Create<OffsetGatherUint2D>));
3562 	addChild(new TestSubcase(m_context, "offset-gather-depth-2d", TestSubcase::Create<OffsetGatherDepth2D>));
3563 	addChild(new TestSubcase(m_context, "offset-gather-float-2darray", TestSubcase::Create<OffsetGatherFloat2DArray>));
3564 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2darray", TestSubcase::Create<OffsetGatherUnorm2DArray>));
3565 	addChild(new TestSubcase(m_context, "offset-gather-int-2darray", TestSubcase::Create<OffsetGatherInt2DArray>));
3566 	addChild(new TestSubcase(m_context, "offset-gather-uint-2darray", TestSubcase::Create<OffsetGatherUint2DArray>));
3567 	addChild(new TestSubcase(m_context, "offset-gather-depth-2darray", TestSubcase::Create<OffsetGatherDepth2DArray>));
3568 	addChild(new TestSubcase(m_context, "offset-gather-float-2drect", TestSubcase::Create<OffsetGatherFloat2DRect>));
3569 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2drect", TestSubcase::Create<OffsetGatherUnorm2DRect>));
3570 	addChild(new TestSubcase(m_context, "offset-gather-int-2drect", TestSubcase::Create<OffsetGatherInt2DRect>));
3571 	addChild(new TestSubcase(m_context, "offset-gather-uint-2drect", TestSubcase::Create<OffsetGatherUint2DRect>));
3572 	addChild(new TestSubcase(m_context, "offset-gather-depth-2drect", TestSubcase::Create<OffsetGatherDepth2DRect>));
3573 	addChild(new TestSubcase(m_context, "offsets-gather-float-2d", TestSubcase::Create<OffsetsGatherFloat2D>));
3574 	addChild(new TestSubcase(m_context, "offsets-gather-unorm-2d", TestSubcase::Create<OffsetsGatherUnorm2D>));
3575 	addChild(new TestSubcase(m_context, "offsets-gather-int-2d", TestSubcase::Create<OffsetsGatherInt2D>));
3576 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2d", TestSubcase::Create<OffsetsGatherUint2D>));
3577 	addChild(new TestSubcase(m_context, "offsets-gather-depth-2d", TestSubcase::Create<OffsetsGatherDepth2D>));
3578 	addChild(
3579 		new TestSubcase(m_context, "offsets-gather-float-2darray", TestSubcase::Create<OffsetsGatherFloat2DArray>));
3580 	addChild(
3581 		new TestSubcase(m_context, "offsets-gather-unorm-2darray", TestSubcase::Create<OffsetsGatherUnorm2DArray>));
3582 	addChild(new TestSubcase(m_context, "offsets-gather-int-2darray", TestSubcase::Create<OffsetsGatherInt2DArray>));
3583 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2darray", TestSubcase::Create<OffsetsGatherUint2DArray>));
3584 	addChild(
3585 		new TestSubcase(m_context, "offsets-gather-depth-2darray", TestSubcase::Create<OffsetsGatherDepth2DArray>));
3586 	addChild(new TestSubcase(m_context, "offsets-gather-float-2drect", TestSubcase::Create<OffsetsGatherFloat2DRect>));
3587 	addChild(new TestSubcase(m_context, "offsets-gather-unorm-2drect", TestSubcase::Create<OffsetsGatherUnorm2DRect>));
3588 	addChild(new TestSubcase(m_context, "offsets-gather-int-2drect", TestSubcase::Create<OffsetsGatherInt2DRect>));
3589 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2drect", TestSubcase::Create<OffsetsGatherUint2DRect>));
3590 	addChild(new TestSubcase(m_context, "offsets-gather-depth-2drect", TestSubcase::Create<OffsetsGatherDepth2DRect>));
3591 	addChild(new TestSubcase(m_context, "swizzle", TestSubcase::Create<Swizzle>));
3592 	addChild(new TestSubcase(m_context, "base-level", TestSubcase::Create<BaseLevel>));
3593 	addChild(new TestSubcase(m_context, "incomplete-texture", TestSubcase::Create<IncompleteTexture>));
3594 	addChild(
3595 		new TestSubcase(m_context, "incomplete-texture-last-comp", TestSubcase::Create<IncompleteTextureLastComp>));
3596 	addChild(new TestSubcase(m_context, "triangle-draw", TestSubcase::Create<TriangleDraw>));
3597 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb", TestSubcase::Create<PlainGatherFloat2DSrgb>));
3598 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb-alpha",
3599 							 TestSubcase::Create<PlainGatherFloat2DSrgbAlpha>));
3600 	addChild(new TestSubcase(m_context, "gather-geometry-shader", TestSubcase::Create<GatherGeometryShader>));
3601 	addChild(new TestSubcase(m_context, "gather-tesselation-shader", TestSubcase::Create<GatherTesselationShader>));
3602 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgb", TestSubcase::Create<PlainGatherFloat2DRgb>));
3603 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-r", TestSubcase::Create<PlainGatherFloat2DR>));
3604 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rgb", TestSubcase::Create<OffsetGatherFloat2DRgb>));
3605 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rg", TestSubcase::Create<OffsetGatherFloat2DRg>));
3606 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-r", TestSubcase::Create<OffsetGatherFloat2DR>));
3607 }
3608 
3609 } // gl4cts namespace
3610