Home | History | Annotate | Download | only in gl
      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:
     56 	virtual ~TGBase()
     57 	{
     58 	}
     59 
     60 	TGBase() : renderTarget(m_context.getRenderContext().getRenderTarget()), pixelFormat(renderTarget.getPixelFormat())
     61 	{
     62 		g_color_eps = Vec4(1.f / (float)(1 << pixelFormat.redBits), 1.f / (float)(1 << pixelFormat.greenBits),
     63 						   1.f / (float)(1 << 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 
     70 	int GetWindowWidth()
     71 	{
     72 		return renderTarget.getWidth();
     73 	}
     74 
     75 	int GetWindowHeight()
     76 	{
     77 		return renderTarget.getHeight();
     78 	}
     79 
     80 	virtual std::string Title()
     81 	{
     82 		return "";
     83 	}
     84 
     85 	virtual std::string Purpose()
     86 	{
     87 		return "";
     88 	}
     89 
     90 	virtual std::string Method()
     91 	{
     92 		return "";
     93 	}
     94 
     95 	virtual std::string PassCriteria()
     96 	{
     97 		return "";
     98 	}
     99 
    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 
    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 
    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 
    261 	GLfloat distance(GLfloat p0, GLfloat p1)
    262 	{
    263 		return de::abs(p0 - p1);
    264 	}
    265 
    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 
    279 	virtual long Setup()
    280 	{
    281 		return NO_ERROR;
    282 	}
    283 
    284 	virtual long Cleanup()
    285 	{
    286 		return NO_ERROR;
    287 	}
    288 };
    289 
    290 class GatherEnumsTest : public TGBase
    291 {
    292 	virtual std::string Title()
    293 	{
    294 		return "Basic Enum Test";
    295 	}
    296 
    297 	virtual std::string Purpose()
    298 	{
    299 		return "Verify that gather related enums are correct.";
    300 	}
    301 
    302 	virtual std::string Method()
    303 	{
    304 		return "Query GL_*_TEXTURE_GATHER_OFFSET enums.";
    305 	}
    306 
    307 	virtual std::string PassCriteria()
    308 	{
    309 		return "Values of enums meet GL spec requirements.";
    310 	}
    311 
    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 
    333 	virtual std::string Title()
    334 	{
    335 		return "GLSL Compile Test";
    336 	}
    337 
    338 	virtual std::string Purpose()
    339 	{
    340 		return "Verify that gather functions are visible in the shaders.";
    341 	}
    342 
    343 	virtual std::string Method()
    344 	{
    345 		return "Create shaders which use all types of gather functions.";
    346 	}
    347 
    348 	virtual std::string PassCriteria()
    349 	{
    350 		return "Programs compile and link successfuly.";
    351 	}
    352 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    894 	virtual std::string TestFunction()
    895 	{
    896 		return Sampler() + TextBody();
    897 	}
    898 
    899 	virtual std::string Type()
    900 	{
    901 		return "vec4";
    902 	}
    903 
    904 	virtual std::string Sampler()
    905 	{
    906 		return "uniform sampler2D my_sampler;                      \n";
    907 	}
    908 
    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 
    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 
    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 
    943 	virtual std::string ComputeShader()
    944 	{
    945 		return "#version 400 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 
    960 	virtual void Init()
    961 	{
    962 		CreateTexture2D();
    963 	}
    964 
    965 	virtual void SetRbo()
    966 	{
    967 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 1, 1);
    968 	}
    969 
    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 
    986 	virtual Vec4 Expected()
    987 	{
    988 		return Vec4(0. / 16, 4. / 16, 8. / 16, 12. / 16);
    989 	}
    990 
    991 	virtual GLenum InternalFormat()
    992 	{
    993 		return GL_RGBA32F;
    994 	}
    995 
    996 	virtual GLenum Format()
    997 	{
    998 		return GL_RGBA;
    999 	}
   1000 
   1001 	virtual Vec4 BufferData()
   1002 	{
   1003 		return Vec4(23. / 32, 26. / 32, 5, 3);
   1004 	}
   1005 
   1006 	virtual bool Supported()
   1007 	{
   1008 		return true;
   1009 	}
   1010 
   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 			!m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader"))
   1063 		{
   1064 			m_context.getTestContext().getLog()
   1065 				<< tcu::TestLog::Message << "Expected "
   1066 				<< "GL_ARB_compute_shader or GL_ARB_compute_shader not supported, skipping compute stage"
   1067 				<< tcu::TestLog::EndMessage;
   1068 			return NO_ERROR;
   1069 		}
   1070 		else
   1071 		{
   1072 			return TestCompute();
   1073 		}
   1074 	}
   1075 
   1076 	virtual long TestCompute()
   1077 	{
   1078 		GLuint m_buffer;
   1079 
   1080 		program = CreateComputeProgram(ComputeShader());
   1081 		glLinkProgram(program);
   1082 		if (!CheckProgram(program))
   1083 			return ERROR;
   1084 		glUseProgram(program);
   1085 
   1086 		glUniform4f(glGetUniformLocation(program, "cs_in"), BufferData().x(), BufferData().y(), BufferData().z(),
   1087 					BufferData().w());
   1088 
   1089 		glGenBuffers(1, &m_buffer);
   1090 		glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
   1091 		glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Vec4), NULL, GL_DYNAMIC_DRAW);
   1092 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
   1093 
   1094 		glDispatchCompute(1, 1, 1);
   1095 
   1096 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
   1097 		glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
   1098 		long error = VerifyCompute();
   1099 		glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
   1100 		glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
   1101 		glDeleteBuffers(1, &m_buffer);
   1102 
   1103 		return error;
   1104 	}
   1105 
   1106 	virtual long VerifyCompute()
   1107 	{
   1108 		Vec4* data;
   1109 		data = static_cast<Vec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Vec4), GL_MAP_READ_BIT));
   1110 		if (!ColorEqual(data[0], Expected(), g_color_eps))
   1111 		{ // for unorms
   1112 			m_context.getTestContext().getLog()
   1113 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1114 				<< Expected().z() << ", " << Expected().w() << " got: " << data[0].x() << ", " << data[0].y() << ", "
   1115 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1116 			return ERROR;
   1117 		}
   1118 		return NO_ERROR;
   1119 	}
   1120 
   1121 	virtual long Cleanup()
   1122 	{
   1123 		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
   1124 		glDisableVertexAttribArray(0);
   1125 		glDeleteTextures(1, &tex);
   1126 		glDeleteVertexArrays(1, &vao);
   1127 		glDeleteBuffers(1, &vbo);
   1128 		glDeleteRenderbuffers(1, &rbo);
   1129 		glDeleteFramebuffers(1, &fbo);
   1130 		glDeleteProgram(program);
   1131 		return NO_ERROR;
   1132 	}
   1133 };
   1134 
   1135 class PlainGatherFloat2DRgba : public GatherBase
   1136 {
   1137 };
   1138 
   1139 class PlainGatherFloat2DRg : public GatherBase
   1140 {
   1141 public:
   1142 	virtual std::string TestFunction()
   1143 	{
   1144 		return "uniform sampler2D my_sampler;                                   \n"
   1145 			   ""
   1146 			   "vec4 test_function(vec4 p) {                                    \n"
   1147 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 1);        \n"
   1148 			   "}\n";
   1149 	}
   1150 
   1151 	virtual Vec4 Expected()
   1152 	{
   1153 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
   1154 	}
   1155 
   1156 	virtual GLenum InternalFormat()
   1157 	{
   1158 		return GL_RG32F;
   1159 	}
   1160 };
   1161 
   1162 class PlainGatherUnorm2D : public GatherBase
   1163 {
   1164 public:
   1165 	virtual GLenum InternalFormat()
   1166 	{
   1167 		return GL_RGBA16;
   1168 	}
   1169 
   1170 	virtual std::string TestFunction()
   1171 	{
   1172 		return "uniform sampler2D my_sampler;                                   \n"
   1173 			   ""
   1174 			   "vec4 test_function(vec4 p) {                                    \n"
   1175 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 0);        \n"
   1176 			   "}\n";
   1177 	}
   1178 };
   1179 
   1180 class PlainGatherInt2DRgba : public GatherBase
   1181 {
   1182 public:
   1183 	virtual GLenum InternalFormat()
   1184 	{
   1185 		return GL_RGBA32I;
   1186 	}
   1187 
   1188 	virtual void Init()
   1189 	{
   1190 		CreateTexture2DInt();
   1191 	}
   1192 
   1193 	virtual void SetRbo()
   1194 	{
   1195 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   1196 	}
   1197 
   1198 	virtual long Verify()
   1199 	{
   1200 		IVec4 data;
   1201 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   1202 		if (data != IVec4(0, 4, 8, 12))
   1203 		{
   1204 			m_context.getTestContext().getLog()
   1205 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   1206 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1207 			return ERROR;
   1208 		}
   1209 		return NO_ERROR;
   1210 	}
   1211 
   1212 	virtual long VerifyCompute()
   1213 	{
   1214 		IVec4* data;
   1215 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1216 		if (data[0] != IVec4(0, 4, 8, 12))
   1217 		{
   1218 			m_context.getTestContext().getLog()
   1219 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1220 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1221 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1222 			return ERROR;
   1223 		}
   1224 		return NO_ERROR;
   1225 	}
   1226 
   1227 	virtual std::string Sampler()
   1228 	{
   1229 		return "uniform isampler2D my_sampler;                     \n";
   1230 	}
   1231 
   1232 	virtual std::string Type()
   1233 	{
   1234 		return "ivec4";
   1235 	}
   1236 };
   1237 
   1238 class PlainGatherInt2DRg : public PlainGatherInt2DRgba
   1239 {
   1240 public:
   1241 	virtual GLenum InternalFormat()
   1242 	{
   1243 		return GL_RG32I;
   1244 	}
   1245 };
   1246 
   1247 class PlainGatherUint2D : public GatherBase
   1248 {
   1249 public:
   1250 	virtual GLenum InternalFormat()
   1251 	{
   1252 		return GL_RGBA32UI;
   1253 	}
   1254 
   1255 	virtual void Init()
   1256 	{
   1257 		CreateTexture2DInt();
   1258 	}
   1259 
   1260 	virtual void SetRbo()
   1261 	{
   1262 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
   1263 	}
   1264 
   1265 	virtual long Verify()
   1266 	{
   1267 		IVec4 data;
   1268 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
   1269 		if (data != IVec4(2, 6, 10, 14))
   1270 		{
   1271 			m_context.getTestContext().getLog()
   1272 				<< tcu::TestLog::Message << "Expected 2, 6, 10, 14, got: " << data.x() << ", " << data.y() << ", "
   1273 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1274 			return ERROR;
   1275 		}
   1276 		return NO_ERROR;
   1277 	}
   1278 
   1279 	virtual long VerifyCompute()
   1280 	{
   1281 		IVec4* data;
   1282 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1283 		if (data[0] != IVec4(2, 6, 10, 14))
   1284 		{
   1285 			m_context.getTestContext().getLog()
   1286 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1287 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1288 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1289 			return ERROR;
   1290 		}
   1291 		return NO_ERROR;
   1292 	}
   1293 
   1294 	virtual std::string Sampler()
   1295 	{
   1296 		return "uniform usampler2D my_sampler;                     \n";
   1297 	}
   1298 
   1299 	virtual Vec4 BufferData()
   1300 	{
   1301 		return Vec4(22.9f / 32, 25.9f / 32, 2, 2);
   1302 	}
   1303 
   1304 	virtual std::string Type()
   1305 	{
   1306 		return "uvec4";
   1307 	}
   1308 
   1309 	virtual std::string TextBody()
   1310 	{
   1311 		return Type() + " test_function(vec4 p) {                                   \n"
   1312 						"    return textureGather(my_sampler, vec2(p.x, p.y), 2);            \n"
   1313 						"}\n";
   1314 	}
   1315 };
   1316 
   1317 class PlainGatherDepth2D : public GatherBase
   1318 {
   1319 public:
   1320 	virtual GLenum InternalFormat()
   1321 	{
   1322 		return GL_DEPTH_COMPONENT32F;
   1323 	}
   1324 
   1325 	virtual GLenum Format()
   1326 	{
   1327 		return GL_DEPTH_COMPONENT;
   1328 	}
   1329 
   1330 	virtual void Init()
   1331 	{
   1332 		CreateTexture2D();
   1333 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   1334 	}
   1335 
   1336 	virtual Vec4 Expected()
   1337 	{
   1338 		return Vec4(1, 1, 0, 0);
   1339 	}
   1340 
   1341 	virtual Vec4 BufferData()
   1342 	{
   1343 		return Vec4(23. / 32, 26. / 32, 13.5 / 16, 3);
   1344 	}
   1345 
   1346 	virtual std::string Sampler()
   1347 	{
   1348 		return "uniform sampler2DShadow my_sampler;                     \n";
   1349 	}
   1350 
   1351 	virtual std::string TextBody()
   1352 	{
   1353 		return Type() + " test_function(vec4 p) {                                \n"
   1354 						"    return textureGather(my_sampler, vec2(p.x, p.y), p.z);       \n"
   1355 						"}\n";
   1356 	}
   1357 };
   1358 
   1359 class PlainGatherFloat2DArray : public GatherBase
   1360 {
   1361 public:
   1362 	virtual void Init()
   1363 	{
   1364 		CreateTexture2DArray(9, 5);
   1365 	}
   1366 
   1367 	virtual std::string Sampler()
   1368 	{
   1369 		return "uniform sampler2DArray my_sampler;                     \n";
   1370 	}
   1371 
   1372 	virtual std::string TextBody()
   1373 	{
   1374 		return Type() + " test_function(vec4 p) {                                \n"
   1375 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
   1376 						"}\n";
   1377 	}
   1378 };
   1379 
   1380 class PlainGatherUnorm2DArray : public GatherBase
   1381 {
   1382 public:
   1383 	virtual void Init()
   1384 	{
   1385 		CreateTexture2DArray(7, 3);
   1386 	}
   1387 
   1388 	virtual std::string Sampler()
   1389 	{
   1390 		return "uniform sampler2DArray my_sampler;                     \n";
   1391 	}
   1392 
   1393 	virtual std::string TextBody()
   1394 	{
   1395 		return Type() + " test_function(vec4 p) {                                \n"
   1396 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.w));       \n"
   1397 						"}\n";
   1398 	}
   1399 
   1400 	virtual GLenum InternalFormat()
   1401 	{
   1402 		return GL_RGBA16;
   1403 	}
   1404 };
   1405 
   1406 class PlainGatherInt2DArray : public GatherBase
   1407 {
   1408 public:
   1409 	virtual void Init()
   1410 	{
   1411 		CreateTexture2DArrayInt(20, 11);
   1412 	}
   1413 
   1414 	virtual GLenum InternalFormat()
   1415 	{
   1416 		return GL_RGBA32I;
   1417 	}
   1418 
   1419 	virtual void SetRbo()
   1420 	{
   1421 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   1422 	}
   1423 
   1424 	virtual long Verify()
   1425 	{
   1426 		IVec4 data;
   1427 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   1428 		if (data != IVec4(3, 7, 11, 15))
   1429 		{
   1430 			m_context.getTestContext().getLog()
   1431 				<< tcu::TestLog::Message << "Expected 3, 7, 11, 15, got: " << data.x() << ", " << data.y() << ", "
   1432 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1433 			return ERROR;
   1434 		}
   1435 		return NO_ERROR;
   1436 	}
   1437 
   1438 	virtual long VerifyCompute()
   1439 	{
   1440 		IVec4* data;
   1441 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1442 		if (data[0] != IVec4(3, 7, 11, 15))
   1443 		{
   1444 			m_context.getTestContext().getLog()
   1445 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1446 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1447 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1448 			return ERROR;
   1449 		}
   1450 		return NO_ERROR;
   1451 	}
   1452 
   1453 	virtual std::string Type()
   1454 	{
   1455 		return "ivec4";
   1456 	}
   1457 
   1458 	virtual Vec4 BufferData()
   1459 	{
   1460 		return Vec4(23. / 32, 26. / 32, 11, 3);
   1461 	}
   1462 
   1463 	virtual std::string Sampler()
   1464 	{
   1465 		return "uniform isampler2DArray my_sampler;                     \n";
   1466 	}
   1467 
   1468 	virtual std::string TextBody()
   1469 	{
   1470 		return Type() + " test_function(vec4 p) {                                \n"
   1471 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 3);    \n"
   1472 						"}\n";
   1473 	}
   1474 };
   1475 
   1476 class PlainGatherUint2DArray : public GatherBase
   1477 {
   1478 public:
   1479 	virtual void Init()
   1480 	{
   1481 		CreateTexture2DArrayInt(3, 1);
   1482 	}
   1483 
   1484 	virtual GLenum InternalFormat()
   1485 	{
   1486 		return GL_RGBA32UI;
   1487 	}
   1488 
   1489 	virtual void SetRbo()
   1490 	{
   1491 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
   1492 	}
   1493 
   1494 	virtual long Verify()
   1495 	{
   1496 		IVec4 data;
   1497 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
   1498 		if (data != IVec4(0, 4, 8, 12))
   1499 		{
   1500 			m_context.getTestContext().getLog()
   1501 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   1502 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1503 			return ERROR;
   1504 		}
   1505 		return NO_ERROR;
   1506 	}
   1507 
   1508 	virtual long VerifyCompute()
   1509 	{
   1510 		IVec4* data;
   1511 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1512 		if (data[0] != IVec4(0, 4, 8, 12))
   1513 		{
   1514 			m_context.getTestContext().getLog()
   1515 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1516 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1517 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1518 			return ERROR;
   1519 		}
   1520 		return NO_ERROR;
   1521 	}
   1522 
   1523 	virtual std::string Type()
   1524 	{
   1525 		return "uvec4";
   1526 	}
   1527 
   1528 	virtual Vec4 BufferData()
   1529 	{
   1530 		return Vec4(23. / 32, 26. / 32, 1, 3);
   1531 	}
   1532 
   1533 	virtual std::string Sampler()
   1534 	{
   1535 		return "uniform usampler2DArray my_sampler;                     \n";
   1536 	}
   1537 
   1538 	virtual std::string TextBody()
   1539 	{
   1540 		return Type() + " test_function(vec4 p) {                                \n"
   1541 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
   1542 						"}\n";
   1543 	}
   1544 };
   1545 
   1546 class PlainGatherDepth2DArray : public GatherBase
   1547 {
   1548 public:
   1549 	virtual GLenum InternalFormat()
   1550 	{
   1551 		return GL_DEPTH_COMPONENT32F;
   1552 	}
   1553 
   1554 	virtual GLenum Format()
   1555 	{
   1556 		return GL_DEPTH_COMPONENT;
   1557 	}
   1558 
   1559 	virtual void Init()
   1560 	{
   1561 		CreateTexture2DArray(9, 5);
   1562 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   1563 	}
   1564 
   1565 	virtual Vec4 Expected()
   1566 	{
   1567 		return Vec4(1, 1, 0, 0);
   1568 	}
   1569 
   1570 	virtual Vec4 BufferData()
   1571 	{
   1572 		return Vec4(23. / 32, 26. / 32, 5, 13.5 / 16);
   1573 	}
   1574 
   1575 	virtual std::string Sampler()
   1576 	{
   1577 		return "uniform sampler2DArrayShadow my_sampler;                     \n";
   1578 	}
   1579 
   1580 	virtual std::string TextBody()
   1581 	{
   1582 		return Type() + " test_function(vec4 p) {                                \n"
   1583 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w);       \n"
   1584 						"}\n";
   1585 	}
   1586 };
   1587 
   1588 class PlainGatherFloatCubeRgba : public GatherBase
   1589 {
   1590 public:
   1591 	virtual void Init()
   1592 	{
   1593 		CreateTextureCube();
   1594 	}
   1595 
   1596 	virtual Vec4 BufferData()
   1597 	{
   1598 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1599 	}
   1600 
   1601 	virtual std::string Sampler()
   1602 	{
   1603 		return "uniform samplerCube my_sampler;                     \n";
   1604 	}
   1605 
   1606 	virtual std::string TextBody()
   1607 	{
   1608 		return Type() + " test_function(vec4 p) {                                \n"
   1609 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
   1610 						"}\n";
   1611 	}
   1612 };
   1613 
   1614 class PlainGatherFloatCubeRg : public GatherBase
   1615 {
   1616 public:
   1617 	virtual void Init()
   1618 	{
   1619 		CreateTextureCube();
   1620 	}
   1621 
   1622 	virtual Vec4 BufferData()
   1623 	{
   1624 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1625 	}
   1626 
   1627 	virtual std::string Sampler()
   1628 	{
   1629 		return "uniform samplerCube my_sampler;                     \n";
   1630 	}
   1631 
   1632 	virtual std::string TextBody()
   1633 	{
   1634 		return Type() + " test_function(vec4 p) {                                \n"
   1635 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 1);    \n"
   1636 						"}\n";
   1637 	}
   1638 
   1639 	virtual Vec4 Expected()
   1640 	{
   1641 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
   1642 	}
   1643 
   1644 	virtual GLenum InternalFormat()
   1645 	{
   1646 		return GL_RG32F;
   1647 	}
   1648 };
   1649 
   1650 class PlainGatherUnormCube : public GatherBase
   1651 {
   1652 public:
   1653 	virtual void Init()
   1654 	{
   1655 		CreateTextureCube();
   1656 	}
   1657 
   1658 	virtual Vec4 BufferData()
   1659 	{
   1660 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1661 	}
   1662 
   1663 	virtual std::string Sampler()
   1664 	{
   1665 		return "uniform samplerCube my_sampler;                     \n";
   1666 	}
   1667 
   1668 	virtual std::string TextBody()
   1669 	{
   1670 		return Type() + " test_function(vec4 p) {                                \n"
   1671 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
   1672 						"}\n";
   1673 	}
   1674 
   1675 	virtual GLenum InternalFormat()
   1676 	{
   1677 		return GL_RGBA16;
   1678 	}
   1679 };
   1680 
   1681 class PlainGatherIntCubeRgba : public GatherBase
   1682 {
   1683 public:
   1684 	virtual void Init()
   1685 	{
   1686 		CreateTextureCubeInt();
   1687 	}
   1688 
   1689 	virtual Vec4 BufferData()
   1690 	{
   1691 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1692 	}
   1693 
   1694 	virtual std::string Sampler()
   1695 	{
   1696 		return "uniform isamplerCube my_sampler;                     \n";
   1697 	}
   1698 
   1699 	virtual std::string TextBody()
   1700 	{
   1701 		return Type() + " test_function(vec4 p) {                                \n"
   1702 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z));       \n"
   1703 						"}\n";
   1704 	}
   1705 
   1706 	virtual GLenum InternalFormat()
   1707 	{
   1708 		return GL_RGBA32I;
   1709 	}
   1710 
   1711 	virtual void SetRbo()
   1712 	{
   1713 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   1714 	}
   1715 
   1716 	virtual long Verify()
   1717 	{
   1718 		IVec4 data;
   1719 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   1720 		if (data != IVec4(0, 4, 8, 12))
   1721 		{
   1722 			m_context.getTestContext().getLog()
   1723 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   1724 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1725 			return ERROR;
   1726 		}
   1727 		return NO_ERROR;
   1728 	}
   1729 
   1730 	virtual long VerifyCompute()
   1731 	{
   1732 		IVec4* data;
   1733 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1734 		if (data[0] != IVec4(0, 4, 8, 12))
   1735 		{
   1736 			m_context.getTestContext().getLog()
   1737 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1738 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1739 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1740 			return ERROR;
   1741 		}
   1742 		return NO_ERROR;
   1743 	}
   1744 
   1745 	virtual std::string Type()
   1746 	{
   1747 		return "ivec4";
   1748 	}
   1749 };
   1750 
   1751 class PlainGatherIntCubeRg : public GatherBase
   1752 {
   1753 public:
   1754 	virtual void Init()
   1755 	{
   1756 		CreateTextureCubeInt();
   1757 	}
   1758 
   1759 	virtual Vec4 BufferData()
   1760 	{
   1761 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1762 	}
   1763 
   1764 	virtual std::string Sampler()
   1765 	{
   1766 		return "uniform isamplerCube my_sampler;                     \n";
   1767 	}
   1768 
   1769 	virtual std::string TextBody()
   1770 	{
   1771 		return Type() + " test_function(vec4 p) {                                \n"
   1772 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 1);    \n"
   1773 						"}\n";
   1774 	}
   1775 
   1776 	virtual GLenum InternalFormat()
   1777 	{
   1778 		return GL_RG32I;
   1779 	}
   1780 
   1781 	virtual void SetRbo()
   1782 	{
   1783 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   1784 	}
   1785 
   1786 	virtual long Verify()
   1787 	{
   1788 		IVec4 data;
   1789 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   1790 		if (data != IVec4(1, 5, 9, 13))
   1791 		{
   1792 			m_context.getTestContext().getLog()
   1793 				<< tcu::TestLog::Message << "Expected 1, 5, 9, 13, got: " << data.x() << ", " << data.y() << ", "
   1794 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1795 			return ERROR;
   1796 		}
   1797 		return NO_ERROR;
   1798 	}
   1799 
   1800 	virtual long VerifyCompute()
   1801 	{
   1802 		IVec4* data;
   1803 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1804 		if (data[0] != IVec4(1, 5, 9, 13))
   1805 		{
   1806 			m_context.getTestContext().getLog()
   1807 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1808 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1809 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1810 			return ERROR;
   1811 		}
   1812 		return NO_ERROR;
   1813 	}
   1814 
   1815 	virtual std::string Type()
   1816 	{
   1817 		return "ivec4";
   1818 	}
   1819 };
   1820 
   1821 class PlainGatherUintCube : public GatherBase
   1822 {
   1823 public:
   1824 	virtual void Init()
   1825 	{
   1826 		CreateTextureCubeInt();
   1827 	}
   1828 
   1829 	virtual Vec4 BufferData()
   1830 	{
   1831 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1832 	}
   1833 
   1834 	virtual std::string Sampler()
   1835 	{
   1836 		return "uniform usamplerCube my_sampler;                     \n";
   1837 	}
   1838 
   1839 	virtual std::string TextBody()
   1840 	{
   1841 		return Type() + " test_function(vec4 p) {                                \n"
   1842 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), 0);    \n"
   1843 						"}\n";
   1844 	}
   1845 
   1846 	virtual GLenum InternalFormat()
   1847 	{
   1848 		return GL_RGBA32UI;
   1849 	}
   1850 
   1851 	virtual void SetRbo()
   1852 	{
   1853 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
   1854 	}
   1855 
   1856 	virtual long Verify()
   1857 	{
   1858 		IVec4 data;
   1859 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   1860 		if (data != IVec4(0, 4, 8, 12))
   1861 		{
   1862 			m_context.getTestContext().getLog()
   1863 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   1864 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   1865 			return ERROR;
   1866 		}
   1867 		return NO_ERROR;
   1868 	}
   1869 
   1870 	virtual long VerifyCompute()
   1871 	{
   1872 		IVec4* data;
   1873 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   1874 		if (data[0] != IVec4(0, 4, 8, 12))
   1875 		{
   1876 			m_context.getTestContext().getLog()
   1877 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   1878 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   1879 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   1880 			return ERROR;
   1881 		}
   1882 		return NO_ERROR;
   1883 	}
   1884 
   1885 	virtual std::string Type()
   1886 	{
   1887 		return "uvec4";
   1888 	}
   1889 };
   1890 
   1891 class PlainGatherDepthCube : public GatherBase
   1892 {
   1893 public:
   1894 	virtual void Init()
   1895 	{
   1896 		CreateTextureCube();
   1897 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   1898 	}
   1899 
   1900 	virtual GLenum InternalFormat()
   1901 	{
   1902 		return GL_DEPTH_COMPONENT32F;
   1903 	}
   1904 
   1905 	virtual GLenum Format()
   1906 	{
   1907 		return GL_DEPTH_COMPONENT;
   1908 	}
   1909 
   1910 	virtual Vec4 BufferData()
   1911 	{
   1912 		return Vec4(7. / 16, -10. / 16, 1, 7.5 / 16);
   1913 	}
   1914 
   1915 	virtual std::string Sampler()
   1916 	{
   1917 		return "uniform samplerCubeShadow my_sampler;                     \n";
   1918 	}
   1919 
   1920 	virtual std::string TextBody()
   1921 	{
   1922 		return Type() + " test_function(vec4 p) {                                \n"
   1923 						"    return textureGather(my_sampler, vec3(p.x, p.y, p.z), p.w);  \n"
   1924 						"}\n";
   1925 	}
   1926 
   1927 	virtual Vec4 Expected()
   1928 	{
   1929 		return Vec4(0, 0, 1, 1);
   1930 	}
   1931 };
   1932 
   1933 class PlainGatherFloatCubeArray : public GatherBase
   1934 {
   1935 public:
   1936 	virtual bool Supported()
   1937 	{
   1938 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
   1939 		{
   1940 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
   1941 			return false;
   1942 		}
   1943 		return true;
   1944 	}
   1945 
   1946 	virtual void Init()
   1947 	{
   1948 		CreateTextureCubeArray(9, 5);
   1949 	}
   1950 
   1951 	virtual Vec4 BufferData()
   1952 	{
   1953 		return Vec4(7. / 16, -10. / 16, 1, 5);
   1954 	}
   1955 
   1956 	virtual std::string Sampler()
   1957 	{
   1958 		return "uniform samplerCubeArray my_sampler;                     \n";
   1959 	}
   1960 
   1961 	virtual std::string TextBody()
   1962 	{
   1963 		return Type() + " test_function(vec4 p) {              \n"
   1964 						"    return textureGather(my_sampler, p);       \n"
   1965 						"}\n";
   1966 	}
   1967 };
   1968 
   1969 class PlainGatherUnormCubeArray : public GatherBase
   1970 {
   1971 public:
   1972 	virtual bool Supported()
   1973 	{
   1974 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
   1975 		{
   1976 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
   1977 			return false;
   1978 		}
   1979 		return true;
   1980 	}
   1981 
   1982 	virtual void Init()
   1983 	{
   1984 		CreateTextureCubeArray(7, 3);
   1985 	}
   1986 
   1987 	virtual Vec4 BufferData()
   1988 	{
   1989 		return Vec4(7. / 16, -10. / 16, 1, 3);
   1990 	}
   1991 
   1992 	virtual std::string Sampler()
   1993 	{
   1994 		return "uniform samplerCubeArray my_sampler;                     \n";
   1995 	}
   1996 
   1997 	virtual std::string TextBody()
   1998 	{
   1999 		return Type() + " test_function(vec4 p) {              \n"
   2000 						"    return textureGather(my_sampler, p);       \n"
   2001 						"}\n";
   2002 	}
   2003 
   2004 	virtual GLenum InternalFormat()
   2005 	{
   2006 		return GL_RGBA16;
   2007 	}
   2008 };
   2009 
   2010 class PlainGatherIntCubeArray : public GatherBase
   2011 {
   2012 public:
   2013 	virtual bool Supported()
   2014 	{
   2015 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
   2016 		{
   2017 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
   2018 			return false;
   2019 		}
   2020 		return true;
   2021 	}
   2022 
   2023 	virtual void Init()
   2024 	{
   2025 		CreateTextureCubeArrayInt(20, 11);
   2026 	}
   2027 
   2028 	virtual Vec4 BufferData()
   2029 	{
   2030 		return Vec4(7. / 16, -10. / 16, 1, 11);
   2031 	}
   2032 
   2033 	virtual std::string Sampler()
   2034 	{
   2035 		return "uniform isamplerCubeArray my_sampler;                     \n";
   2036 	}
   2037 
   2038 	virtual std::string TextBody()
   2039 	{
   2040 		return Type() + " test_function(vec4 p) {              \n"
   2041 						"    return textureGather(my_sampler, p);       \n"
   2042 						"}\n";
   2043 	}
   2044 
   2045 	virtual GLenum InternalFormat()
   2046 	{
   2047 		return GL_RGBA32I;
   2048 	}
   2049 
   2050 	virtual void SetRbo()
   2051 	{
   2052 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   2053 	}
   2054 
   2055 	virtual long Verify()
   2056 	{
   2057 		IVec4 data;
   2058 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   2059 		if (data != IVec4(0, 4, 8, 12))
   2060 		{
   2061 			m_context.getTestContext().getLog()
   2062 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   2063 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   2064 			return ERROR;
   2065 		}
   2066 		return NO_ERROR;
   2067 	}
   2068 
   2069 	virtual long VerifyCompute()
   2070 	{
   2071 		IVec4* data;
   2072 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   2073 		if (data[0] != IVec4(0, 4, 8, 12))
   2074 		{
   2075 			m_context.getTestContext().getLog()
   2076 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   2077 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   2078 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   2079 			return ERROR;
   2080 		}
   2081 		return NO_ERROR;
   2082 	}
   2083 
   2084 	virtual std::string Type()
   2085 	{
   2086 		return "ivec4";
   2087 	}
   2088 };
   2089 
   2090 class PlainGatherUintCubeArray : public GatherBase
   2091 {
   2092 public:
   2093 	virtual bool Supported()
   2094 	{
   2095 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
   2096 		{
   2097 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
   2098 			return false;
   2099 		}
   2100 		return true;
   2101 	}
   2102 
   2103 	virtual void Init()
   2104 	{
   2105 		CreateTextureCubeArrayInt(3, 1);
   2106 	}
   2107 
   2108 	virtual Vec4 BufferData()
   2109 	{
   2110 		return Vec4(7. / 16, -10. / 16, 1, 1);
   2111 	}
   2112 
   2113 	virtual std::string Sampler()
   2114 	{
   2115 		return "uniform usamplerCubeArray my_sampler;                     \n";
   2116 	}
   2117 
   2118 	virtual std::string TextBody()
   2119 	{
   2120 		return Type() + " test_function(vec4 p) {              \n"
   2121 						"    return textureGather(my_sampler, p);       \n"
   2122 						"}\n";
   2123 	}
   2124 
   2125 	virtual GLenum InternalFormat()
   2126 	{
   2127 		return GL_RGBA32UI;
   2128 	}
   2129 
   2130 	virtual void SetRbo()
   2131 	{
   2132 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
   2133 	}
   2134 
   2135 	virtual long Verify()
   2136 	{
   2137 		UVec4 data;
   2138 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
   2139 		if (data != UVec4(0, 4, 8, 12))
   2140 		{
   2141 			m_context.getTestContext().getLog()
   2142 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   2143 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   2144 			return ERROR;
   2145 		}
   2146 		return NO_ERROR;
   2147 	}
   2148 
   2149 	virtual long VerifyCompute()
   2150 	{
   2151 		IVec4* data;
   2152 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   2153 		if (data[0] != IVec4(0, 4, 8, 12))
   2154 		{
   2155 			m_context.getTestContext().getLog()
   2156 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   2157 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   2158 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   2159 			return ERROR;
   2160 		}
   2161 		return NO_ERROR;
   2162 	}
   2163 
   2164 	virtual std::string Type()
   2165 	{
   2166 		return "uvec4";
   2167 	}
   2168 };
   2169 
   2170 class PlainGatherDepthCubeArray : public GatherBase
   2171 {
   2172 public:
   2173 	virtual bool Supported()
   2174 	{
   2175 		if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_cube_map_array"))
   2176 		{
   2177 			OutputNotSupported("GL_ARB_texture_cube_map_array not supported");
   2178 			return false;
   2179 		}
   2180 		return true;
   2181 	}
   2182 
   2183 	virtual void Init()
   2184 	{
   2185 		CreateTextureCubeArray(7, 3);
   2186 		glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   2187 	}
   2188 
   2189 	virtual Vec4 BufferData()
   2190 	{
   2191 		return Vec4(7. / 16, -10. / 16, 1, 3);
   2192 	}
   2193 
   2194 	virtual std::string Sampler()
   2195 	{
   2196 		return "uniform samplerCubeArrayShadow my_sampler;                     \n";
   2197 	}
   2198 
   2199 	virtual std::string TextBody()
   2200 	{
   2201 		return Type() + " test_function(vec4 p) {                   \n"
   2202 						"    return textureGather(my_sampler, p, 7.5/16);    \n"
   2203 						"}\n";
   2204 	}
   2205 
   2206 	virtual GLenum InternalFormat()
   2207 	{
   2208 		return GL_DEPTH_COMPONENT32F;
   2209 	}
   2210 
   2211 	virtual GLenum Format()
   2212 	{
   2213 		return GL_DEPTH_COMPONENT;
   2214 	}
   2215 
   2216 	virtual Vec4 Expected()
   2217 	{
   2218 		return Vec4(0, 0, 1, 1);
   2219 	}
   2220 };
   2221 
   2222 class PlainGatherFloat2DRect : public GatherBase
   2223 {
   2224 public:
   2225 	virtual void Init()
   2226 	{
   2227 		CreateTexture2D(true);
   2228 	}
   2229 
   2230 	virtual Vec4 BufferData()
   2231 	{
   2232 		return Vec4(23, 26, 0, 0);
   2233 	}
   2234 
   2235 	virtual std::string Sampler()
   2236 	{
   2237 		return "uniform sampler2DRect my_sampler;                     \n";
   2238 	}
   2239 
   2240 	virtual Vec4 Expected()
   2241 	{
   2242 		return Vec4(1. / 16, 5. / 16, 9. / 16, 13. / 16);
   2243 	}
   2244 
   2245 	virtual std::string TextBody()
   2246 	{
   2247 		return Type() + " test_function(vec4 p) {                          \n"
   2248 						"    return textureGather(my_sampler, vec2(p.x, p.y), 1);   \n"
   2249 						"}\n";
   2250 	}
   2251 };
   2252 
   2253 class PlainGatherUnorm2DRect : public GatherBase
   2254 {
   2255 public:
   2256 	virtual void Init()
   2257 	{
   2258 		CreateTexture2D(true);
   2259 	}
   2260 
   2261 	virtual Vec4 BufferData()
   2262 	{
   2263 		return Vec4(23, 26, 0, 0);
   2264 	}
   2265 
   2266 	virtual std::string Sampler()
   2267 	{
   2268 		return "uniform sampler2DRect my_sampler;                     \n";
   2269 	}
   2270 
   2271 	virtual std::string TextBody()
   2272 	{
   2273 		return Type() + " test_function(vec4 p) {                       \n"
   2274 						"    return textureGather(my_sampler, vec2(p.x, p.y));   \n"
   2275 						"}\n";
   2276 	}
   2277 
   2278 	virtual GLenum InternalFormat()
   2279 	{
   2280 		return GL_RGBA16;
   2281 	}
   2282 };
   2283 
   2284 class PlainGatherInt2DRect : public GatherBase
   2285 {
   2286 public:
   2287 	virtual void Init()
   2288 	{
   2289 		CreateTexture2DInt(true);
   2290 	}
   2291 
   2292 	virtual Vec4 BufferData()
   2293 	{
   2294 		return Vec4(22.9f, 25.9f, 0, 0);
   2295 	}
   2296 
   2297 	virtual std::string Sampler()
   2298 	{
   2299 		return "uniform isampler2DRect my_sampler;                     \n";
   2300 	}
   2301 
   2302 	virtual std::string TextBody()
   2303 	{
   2304 		return Type() + " test_function(vec4 p) {                        \n"
   2305 						"    return textureGather(my_sampler, vec2(p.x, p.y));    \n"
   2306 						"}\n";
   2307 	}
   2308 
   2309 	virtual GLenum InternalFormat()
   2310 	{
   2311 		return GL_RGBA32I;
   2312 	}
   2313 
   2314 	virtual void SetRbo()
   2315 	{
   2316 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32I, 1, 1);
   2317 	}
   2318 
   2319 	virtual long Verify()
   2320 	{
   2321 		IVec4 data;
   2322 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_INT, &data);
   2323 		if (data != IVec4(0, 4, 8, 12))
   2324 		{
   2325 			m_context.getTestContext().getLog()
   2326 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   2327 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   2328 			return ERROR;
   2329 		}
   2330 		return NO_ERROR;
   2331 	}
   2332 
   2333 	virtual long VerifyCompute()
   2334 	{
   2335 		IVec4* data;
   2336 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   2337 		if (data[0] != IVec4(0, 4, 8, 12))
   2338 		{
   2339 			m_context.getTestContext().getLog()
   2340 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   2341 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   2342 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   2343 			return ERROR;
   2344 		}
   2345 		return NO_ERROR;
   2346 	}
   2347 
   2348 	virtual std::string Type()
   2349 	{
   2350 		return "ivec4";
   2351 	}
   2352 };
   2353 
   2354 class PlainGatherUint2DRect : public GatherBase
   2355 {
   2356 public:
   2357 	virtual void Init()
   2358 	{
   2359 		CreateTexture2DInt(true);
   2360 	}
   2361 
   2362 	virtual Vec4 BufferData()
   2363 	{
   2364 		return Vec4(22.9f, 25.9f, 0, 0);
   2365 	}
   2366 
   2367 	virtual std::string Sampler()
   2368 	{
   2369 		return "uniform usampler2DRect my_sampler;                     \n";
   2370 	}
   2371 
   2372 	virtual std::string TextBody()
   2373 	{
   2374 		return Type() + " test_function(vec4 p) {                        \n"
   2375 						"    return textureGather(my_sampler, vec2(p.x, p.y));    \n"
   2376 						"}\n";
   2377 	}
   2378 
   2379 	virtual GLenum InternalFormat()
   2380 	{
   2381 		return GL_RGBA32UI;
   2382 	}
   2383 
   2384 	virtual void SetRbo()
   2385 	{
   2386 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32UI, 1, 1);
   2387 	}
   2388 
   2389 	virtual long Verify()
   2390 	{
   2391 		UVec4 data;
   2392 		glReadPixels(0, 0, 1, 1, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data);
   2393 		if (data != UVec4(0, 4, 8, 12))
   2394 		{
   2395 			m_context.getTestContext().getLog()
   2396 				<< tcu::TestLog::Message << "Expected 0, 4, 8, 12, got: " << data.x() << ", " << data.y() << ", "
   2397 				<< data.z() << ", " << data.w() << tcu::TestLog::EndMessage;
   2398 			return ERROR;
   2399 		}
   2400 		return NO_ERROR;
   2401 	}
   2402 
   2403 	virtual long VerifyCompute()
   2404 	{
   2405 		IVec4* data;
   2406 		data = static_cast<IVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(IVec4), GL_MAP_READ_BIT));
   2407 		if (data[0] != IVec4(0, 4, 8, 12))
   2408 		{
   2409 			m_context.getTestContext().getLog()
   2410 				<< tcu::TestLog::Message << "Expected " << Expected().x() << ", " << Expected().y() << ", "
   2411 				<< Expected().z() << ", " << Expected().w() << ", got: " << data[0].x() << ", " << data[0].y() << ", "
   2412 				<< data[0].z() << ", " << data[0].w() << tcu::TestLog::EndMessage;
   2413 			return ERROR;
   2414 		}
   2415 		return NO_ERROR;
   2416 	}
   2417 
   2418 	virtual std::string Type()
   2419 	{
   2420 		return "uvec4";
   2421 	}
   2422 };
   2423 
   2424 class PlainGatherDepth2DRect : public GatherBase
   2425 {
   2426 public:
   2427 	virtual void Init()
   2428 	{
   2429 		CreateTexture2D(true);
   2430 		glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   2431 	}
   2432 
   2433 	virtual Vec4 BufferData()
   2434 	{
   2435 		return Vec4(23, 26, 13.5 / 16, 3);
   2436 	}
   2437 
   2438 	virtual std::string Sampler()
   2439 	{
   2440 		return "uniform sampler2DRectShadow my_sampler;                     \n";
   2441 	}
   2442 
   2443 	virtual std::string TextBody()
   2444 	{
   2445 		return Type() + " test_function(vec4 p) {                             \n"
   2446 						"    return textureGather(my_sampler, vec2(p.x, p.y), p.z);    \n"
   2447 						"}\n";
   2448 	}
   2449 
   2450 	virtual GLenum InternalFormat()
   2451 	{
   2452 		return GL_DEPTH_COMPONENT32F;
   2453 	}
   2454 
   2455 	virtual GLenum Format()
   2456 	{
   2457 		return GL_DEPTH_COMPONENT;
   2458 	}
   2459 
   2460 	virtual Vec4 Expected()
   2461 	{
   2462 		return Vec4(1, 1, 0, 0);
   2463 	}
   2464 };
   2465 
   2466 class OffsetGatherFloat2D : public GatherBase
   2467 {
   2468 	virtual Vec4 BufferData()
   2469 	{
   2470 		return Vec4(19. / 32, 22. / 32, 4, 4);
   2471 	}
   2472 
   2473 	virtual std::string TextBody()
   2474 	{
   2475 		return Type() + " test_function(vec4 p) {                                               \n"
   2476 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
   2477 						"}\n";
   2478 	}
   2479 };
   2480 
   2481 class OffsetGatherUnorm2D : public PlainGatherUnorm2D
   2482 {
   2483 	virtual Vec4 BufferData()
   2484 	{
   2485 		return Vec4(19. / 32, 22. / 32, 4, 4);
   2486 	}
   2487 
   2488 	virtual std::string TestFunction()
   2489 	{
   2490 		return "uniform sampler2D my_sampler;                                   \n"
   2491 			   ""
   2492 			   "vec4 test_function(vec4 p) {                                                    \n"
   2493 			   "    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
   2494 			   "}\n";
   2495 	}
   2496 };
   2497 
   2498 class OffsetGatherInt2D : public PlainGatherInt2DRgba
   2499 {
   2500 	virtual Vec4 BufferData()
   2501 	{
   2502 		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 4);
   2503 	}
   2504 
   2505 	virtual std::string TextBody()
   2506 	{
   2507 		return Type() + " test_function(vec4 p) {                                               \n"
   2508 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)));    \n"
   2509 						"}\n";
   2510 	}
   2511 };
   2512 
   2513 class OffsetGatherUint2D : public PlainGatherUint2D
   2514 {
   2515 	virtual Vec4 BufferData()
   2516 	{
   2517 		return Vec4(18.9f / 32.f, 21.9f / 32.f, 4, 2);
   2518 	}
   2519 
   2520 	virtual std::string TextBody()
   2521 	{
   2522 		return Type() + " test_function(vec4 p) {                                                          \n"
   2523 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z)), 2);            \n"
   2524 						"}\n";
   2525 	}
   2526 };
   2527 
   2528 class OffsetGatherDepth2D : public PlainGatherDepth2D
   2529 {
   2530 	virtual Vec4 BufferData()
   2531 	{
   2532 		return Vec4(19. / 32, 22. / 32, 4, 13.5 / 16);
   2533 	}
   2534 
   2535 	virtual std::string TextBody()
   2536 	{
   2537 		return Type() + " test_function(vec4 p) {                                               \n"
   2538 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), p.w, ivec2(int(p.z)));    \n"
   2539 						"}\n";
   2540 	}
   2541 };
   2542 
   2543 class OffsetGatherFloat2DArray : public PlainGatherFloat2DArray
   2544 {
   2545 	virtual Vec4 BufferData()
   2546 	{
   2547 		return Vec4(19. / 32, 22. / 32, 5, 4);
   2548 	}
   2549 
   2550 	virtual std::string TextBody()
   2551 	{
   2552 		return Type() + " test_function(vec4 p) {                                                    \n"
   2553 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
   2554 						"}\n";
   2555 	}
   2556 };
   2557 
   2558 class OffsetGatherUnorm2DArray : public PlainGatherUnorm2DArray
   2559 {
   2560 	virtual Vec4 BufferData()
   2561 	{
   2562 		return Vec4(19. / 32, 22. / 32, 3, 4);
   2563 	}
   2564 
   2565 	virtual std::string TextBody()
   2566 	{
   2567 		return Type() + " test_function(vec4 p) {                                                    \n"
   2568 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
   2569 						"}\n";
   2570 	}
   2571 };
   2572 
   2573 class OffsetGatherInt2DArray : public PlainGatherInt2DArray
   2574 {
   2575 	virtual Vec4 BufferData()
   2576 	{
   2577 		return Vec4(19. / 32, 22. / 32, 11, 4);
   2578 	}
   2579 
   2580 	virtual std::string TextBody()
   2581 	{
   2582 		return Type() + " test_function(vec4 p) {                                                    \n"
   2583 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)), 3); \n"
   2584 						"}\n";
   2585 	}
   2586 };
   2587 
   2588 class OffsetGatherUint2DArray : public PlainGatherUint2DArray
   2589 {
   2590 	virtual Vec4 BufferData()
   2591 	{
   2592 		return Vec4(19. / 32, 22. / 32, 1, 4);
   2593 	}
   2594 
   2595 	virtual std::string TextBody()
   2596 	{
   2597 		return Type() + " test_function(vec4 p) {                                                    \n"
   2598 						"    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), ivec2(int(p.w)));    \n"
   2599 						"}\n";
   2600 	}
   2601 };
   2602 
   2603 class OffsetGatherDepth2DArray : public PlainGatherDepth2DArray
   2604 {
   2605 	virtual void Init()
   2606 	{
   2607 		CreateTexture2DArray(7, 3);
   2608 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   2609 	}
   2610 
   2611 	virtual Vec4 BufferData()
   2612 	{
   2613 		return Vec4(19. / 32, 22. / 32, 3, 4);
   2614 	}
   2615 
   2616 	virtual std::string TextBody()
   2617 	{
   2618 		return Type() +
   2619 			   " test_function(vec4 p) {                                                                   \n"
   2620 			   "    return textureGatherOffset(my_sampler, vec3(p.x, p.y, p.z), p.y + (5./32), ivec2(int(p.w)));    \n"
   2621 			   "}\n";
   2622 	}
   2623 };
   2624 
   2625 class OffsetGatherFloat2DRect : public PlainGatherFloat2DRect
   2626 {
   2627 	virtual Vec4 BufferData()
   2628 	{
   2629 		return Vec4(19, 22, 0, 4);
   2630 	}
   2631 
   2632 	virtual std::string TextBody()
   2633 	{
   2634 		return Type() + " test_function(vec4 p) {                                                  \n"
   2635 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)), 1);    \n"
   2636 						"}\n";
   2637 	}
   2638 };
   2639 
   2640 class OffsetGatherUnorm2DRect : public PlainGatherUnorm2DRect
   2641 {
   2642 	virtual Vec4 BufferData()
   2643 	{
   2644 		return Vec4(30.9f, 18.9f, -8.f, 7.f);
   2645 	}
   2646 
   2647 	virtual std::string TextBody()
   2648 	{
   2649 		return Type() + " test_function(vec4 p) {                                                         \n"
   2650 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.z), int(p.w)));    \n"
   2651 						"}\n";
   2652 	}
   2653 };
   2654 
   2655 class OffsetGatherInt2DRect : public PlainGatherInt2DRect
   2656 {
   2657 	virtual Vec4 BufferData()
   2658 	{
   2659 		return Vec4(22.9f, 25.9f, 0, 0);
   2660 	}
   2661 
   2662 	virtual std::string TextBody()
   2663 	{
   2664 		return Type() + " test_function(vec4 p) {                                               \n"
   2665 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)));    \n"
   2666 						"}\n";
   2667 	}
   2668 };
   2669 
   2670 class OffsetGatherUint2DRect : public PlainGatherUint2DRect
   2671 {
   2672 	virtual Vec4 BufferData()
   2673 	{
   2674 		return Vec4(26.9f, 29.9f, 0, -4);
   2675 	}
   2676 
   2677 	virtual std::string TextBody()
   2678 	{
   2679 		return Type() + " test_function(vec4 p) {                                               \n"
   2680 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), ivec2(int(p.w)));    \n"
   2681 						"}\n";
   2682 	}
   2683 };
   2684 
   2685 class OffsetGatherDepth2DRect : public PlainGatherDepth2DRect
   2686 {
   2687 	virtual Vec4 BufferData()
   2688 	{
   2689 		return Vec4(19, 22, 13.5 / 16, 4);
   2690 	}
   2691 
   2692 	virtual std::string TextBody()
   2693 	{
   2694 		return Type() + " test_function(vec4 p) {                                                    \n"
   2695 						"    return textureGatherOffset(my_sampler, vec2(p.x, p.y), p.z, ivec2(int(p.w)));    \n"
   2696 						"}\n";
   2697 	}
   2698 };
   2699 
   2700 class OffsetsGatherFloat2D : public OffsetGatherFloat2D
   2701 {
   2702 	virtual Vec4 BufferData()
   2703 	{
   2704 		return Vec4(18. / 32, 8. / 32, 0, 0);
   2705 	}
   2706 
   2707 	virtual std::string TextBody()
   2708 	{
   2709 		return Type() +
   2710 			   " test_function(vec4 p) {                                                             \n"
   2711 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2712 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2713 			   "}\n";
   2714 	}
   2715 };
   2716 
   2717 class OffsetsGatherUnorm2D : public OffsetGatherUnorm2D
   2718 {
   2719 	virtual Vec4 BufferData()
   2720 	{
   2721 		return Vec4(18. / 32, 8. / 32, 0, 0);
   2722 	}
   2723 
   2724 	virtual std::string TestFunction()
   2725 	{
   2726 		return "uniform sampler2D my_sampler;                                   \n"
   2727 			   ""
   2728 			   "vec4  test_function(vec4 p) {                                                             \n"
   2729 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2730 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2731 			   "}\n";
   2732 	}
   2733 };
   2734 
   2735 class OffsetsGatherInt2D : public OffsetGatherInt2D
   2736 {
   2737 	virtual Vec4 BufferData()
   2738 	{
   2739 		return Vec4(18. / 32, 8. / 32, 0, 0);
   2740 	}
   2741 
   2742 	virtual std::string TextBody()
   2743 	{
   2744 		return Type() +
   2745 			   " test_function(vec4 p) {                                                             \n"
   2746 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2747 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2748 			   "}\n";
   2749 	}
   2750 };
   2751 
   2752 class OffsetsGatherUint2D : public OffsetGatherUint2D
   2753 {
   2754 	virtual Vec4 BufferData()
   2755 	{
   2756 		return Vec4(18. / 32, 8. / 32, 2, 2);
   2757 	}
   2758 
   2759 	virtual std::string TextBody()
   2760 	{
   2761 		return Type() +
   2762 			   " test_function(vec4 p) {                                                             \n"
   2763 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2764 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets, 2);                      \n"
   2765 			   "}\n";
   2766 	}
   2767 };
   2768 
   2769 class OffsetsGatherDepth2D : public OffsetGatherDepth2D
   2770 {
   2771 	virtual Vec4 BufferData()
   2772 	{
   2773 		return Vec4(18. / 32, 8. / 32, 0.49f, 0);
   2774 	}
   2775 
   2776 	virtual std::string TextBody()
   2777 	{
   2778 		return Type() +
   2779 			   " test_function(vec4 p) {                                                             \n"
   2780 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2781 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), p.z, offsets);                    \n"
   2782 			   "}\n";
   2783 	}
   2784 
   2785 	virtual Vec4 Expected()
   2786 	{
   2787 		return Vec4(0, 0, 1, 1);
   2788 	}
   2789 };
   2790 
   2791 class OffsetsGatherFloat2DArray : public PlainGatherFloat2DArray
   2792 {
   2793 	virtual void Init()
   2794 	{
   2795 		CreateTexture2DArray(3, 1);
   2796 	}
   2797 
   2798 	virtual Vec4 BufferData()
   2799 	{
   2800 		return Vec4(18. / 32, 8. / 32, 1, 0);
   2801 	}
   2802 
   2803 	virtual std::string TextBody()
   2804 	{
   2805 		return Type() +
   2806 			   " test_function(vec4 p) {                                                             \n"
   2807 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2808 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
   2809 			   "}\n";
   2810 	}
   2811 };
   2812 
   2813 class OffsetsGatherUnorm2DArray : public PlainGatherUnorm2DArray
   2814 {
   2815 	virtual void Init()
   2816 	{
   2817 		CreateTexture2DArray(3, 1);
   2818 	}
   2819 
   2820 	virtual Vec4 BufferData()
   2821 	{
   2822 		return Vec4(18. / 32, 8. / 32, 1, 0);
   2823 	}
   2824 
   2825 	virtual std::string TextBody()
   2826 	{
   2827 		return Type() +
   2828 			   " test_function(vec4 p) {                                                             \n"
   2829 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2830 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
   2831 			   "}\n";
   2832 	}
   2833 };
   2834 
   2835 class OffsetsGatherInt2DArray : public PlainGatherInt2DArray
   2836 {
   2837 	virtual void Init()
   2838 	{
   2839 		CreateTexture2DArrayInt(3, 1);
   2840 	}
   2841 
   2842 	virtual Vec4 BufferData()
   2843 	{
   2844 		return Vec4(18. / 32, 8. / 32, 1, 0);
   2845 	}
   2846 
   2847 	virtual std::string TextBody()
   2848 	{
   2849 		return Type() +
   2850 			   " test_function(vec4 p) {                                                             \n"
   2851 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2852 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets, 3);                 \n"
   2853 			   "}\n";
   2854 	}
   2855 };
   2856 
   2857 class OffsetsGatherUint2DArray : public PlainGatherUint2DArray
   2858 {
   2859 	virtual void Init()
   2860 	{
   2861 		CreateTexture2DArrayInt(3, 1);
   2862 	}
   2863 
   2864 	virtual Vec4 BufferData()
   2865 	{
   2866 		return Vec4(18. / 32, 8. / 32, 1, 0);
   2867 	}
   2868 
   2869 	virtual std::string TextBody()
   2870 	{
   2871 		return Type() +
   2872 			   " test_function(vec4 p) {                                                             \n"
   2873 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2874 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), offsets);                    \n"
   2875 			   "}\n";
   2876 	}
   2877 };
   2878 
   2879 class OffsetsGatherDepth2DArray : public PlainGatherDepth2DArray
   2880 {
   2881 	virtual void Init()
   2882 	{
   2883 		CreateTexture2DArray(3, 1);
   2884 		glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
   2885 	}
   2886 
   2887 	virtual Vec4 BufferData()
   2888 	{
   2889 		return Vec4(18. / 32, 8. / 32, 1, 0.49f);
   2890 	}
   2891 
   2892 	virtual std::string TextBody()
   2893 	{
   2894 		return Type() +
   2895 			   " test_function(vec4 p) {                                                             \n"
   2896 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2897 			   "    return textureGatherOffsets(my_sampler, vec3(p.x, p.y, p.z), p.w, offsets);               \n"
   2898 			   "}\n";
   2899 	}
   2900 
   2901 	virtual Vec4 Expected()
   2902 	{
   2903 		return Vec4(0, 0, 1, 1);
   2904 	}
   2905 };
   2906 
   2907 class OffsetsGatherFloat2DRect : public PlainGatherFloat2DRect
   2908 {
   2909 	virtual Vec4 BufferData()
   2910 	{
   2911 		return Vec4(18, 8, 0, 0);
   2912 	}
   2913 
   2914 	virtual std::string TextBody()
   2915 	{
   2916 		return Type() +
   2917 			   " test_function(vec4 p) {                                                             \n"
   2918 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2919 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets, 1);                      \n"
   2920 			   "}\n";
   2921 	}
   2922 };
   2923 
   2924 class OffsetsGatherUnorm2DRect : public PlainGatherUnorm2DRect
   2925 {
   2926 	virtual Vec4 BufferData()
   2927 	{
   2928 		return Vec4(18, 8, 0, 0);
   2929 	}
   2930 
   2931 	virtual std::string TextBody()
   2932 	{
   2933 		return Type() +
   2934 			   " test_function(vec4 p) {                                                             \n"
   2935 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2936 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2937 			   "}\n";
   2938 	}
   2939 };
   2940 
   2941 class OffsetsGatherInt2DRect : public PlainGatherUint2DRect
   2942 {
   2943 	virtual Vec4 BufferData()
   2944 	{
   2945 		return Vec4(17.9f, 7.9f, 0, 0);
   2946 	}
   2947 
   2948 	virtual std::string TextBody()
   2949 	{
   2950 		return Type() +
   2951 			   " test_function(vec4 p) {                                                             \n"
   2952 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2953 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2954 			   "}\n";
   2955 	}
   2956 };
   2957 
   2958 class OffsetsGatherUint2DRect : public PlainGatherUint2DRect
   2959 {
   2960 	virtual Vec4 BufferData()
   2961 	{
   2962 		return Vec4(17.9f, 7.9f, 0, 0);
   2963 	}
   2964 
   2965 	virtual std::string TextBody()
   2966 	{
   2967 		return Type() +
   2968 			   " test_function(vec4 p) {                                                             \n"
   2969 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2970 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), offsets);                         \n"
   2971 			   "}\n";
   2972 	}
   2973 };
   2974 
   2975 class OffsetsGatherDepth2DRect : public PlainGatherDepth2DRect
   2976 {
   2977 	virtual Vec4 BufferData()
   2978 	{
   2979 		return Vec4(17.9f, 7.9f, 0.49f, 0);
   2980 	}
   2981 
   2982 	virtual std::string TextBody()
   2983 	{
   2984 		return Type() +
   2985 			   " test_function(vec4 p) {                                                             \n"
   2986 			   "    const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3)); \n"
   2987 			   "    return textureGatherOffsets(my_sampler, vec2(p.x, p.y), p.z, offsets);                    \n"
   2988 			   "}\n";
   2989 	}
   2990 
   2991 	virtual Vec4 Expected()
   2992 	{
   2993 		return Vec4(0, 0, 1, 1);
   2994 	}
   2995 };
   2996 
   2997 class Swizzle : public PlainGatherFloat2DRgba
   2998 {
   2999 	virtual std::string TestFunction()
   3000 	{
   3001 		return "uniform sampler2D my_sampler;                                   \n"
   3002 			   ""
   3003 			   "vec4 test_function(vec4 p) {                                    \n"
   3004 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 1).yzww;   \n"
   3005 			   "}\n";
   3006 	}
   3007 
   3008 	virtual Vec4 Expected()
   3009 	{
   3010 		return Vec4(5. / 16, 9. / 16, 13. / 16, 13. / 16);
   3011 	}
   3012 };
   3013 
   3014 class BaseLevel : public PlainGatherFloat2DRgba
   3015 {
   3016 	virtual void Init()
   3017 	{
   3018 		CreateTexture2D(false, true);
   3019 	}
   3020 };
   3021 
   3022 class IncompleteTexture : public PlainGatherFloat2DRgba
   3023 {
   3024 	virtual void Init()
   3025 	{
   3026 		CreateTexture2D();
   3027 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
   3028 	}
   3029 
   3030 	virtual Vec4 Expected()
   3031 	{
   3032 		return Vec4(0);
   3033 	}
   3034 };
   3035 
   3036 class IncompleteTextureLastComp : public PlainGatherFloat2DRgba
   3037 {
   3038 	virtual void Init()
   3039 	{
   3040 		CreateTexture2D();
   3041 		glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, 0);
   3042 	}
   3043 
   3044 	virtual Vec4 Expected()
   3045 	{
   3046 		return Vec4(1);
   3047 	}
   3048 
   3049 	virtual std::string TestFunction()
   3050 	{
   3051 		return "uniform sampler2D my_sampler;                                   \n"
   3052 			   ""
   3053 			   "vec4 test_function(vec4 p) {                                    \n"
   3054 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 3);        \n"
   3055 			   "}\n";
   3056 	}
   3057 };
   3058 
   3059 class TriangleDraw : public GatherBase
   3060 {
   3061 	GLuint program, rbo, fbo, vao, vbo;
   3062 
   3063 	virtual std::string VertexShader()
   3064 	{
   3065 		return "#version 400                                  \n"
   3066 			   "out vec2 texcoords;                           \n"
   3067 			   "in vec4 Vertex;                               \n"
   3068 			   "void main() {                                 \n"
   3069 			   "   gl_Position = Vertex;                      \n"
   3070 			   "   texcoords = (Vertex.xy + vec2(1.0)) / 2.0; \n"
   3071 			   "}\n";
   3072 	}
   3073 
   3074 	virtual std::string FragmentShader()
   3075 	{
   3076 		return "#version 400                                      \n"
   3077 			   "in vec2 texcoords;                                \n"
   3078 			   "out vec4 FragColor;                               \n"
   3079 			   "uniform sampler2D tex;                            \n"
   3080 			   "void main() {                                     \n"
   3081 			   "   FragColor = textureGather(tex, texcoords, 2);  \n"
   3082 			   "}\n";
   3083 	}
   3084 
   3085 	virtual long Run()
   3086 	{
   3087 		glGenFramebuffers(1, &fbo);
   3088 		glGenRenderbuffers(1, &rbo);
   3089 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
   3090 		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 100, 100);
   3091 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
   3092 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
   3093 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
   3094 		glDrawBuffers(1, &drawBuffer);
   3095 		GLfloat colorf[4] = { 0, 0, 0, 0 };
   3096 		glClearBufferfv(GL_COLOR, 0, colorf);
   3097 		glViewport(0, 0, 100, 100);
   3098 
   3099 		program = CreateProgram(VertexShader().c_str(), NULL, NULL, NULL, FragmentShader().c_str());
   3100 		glBindAttribLocation(program, 0, "Vertex");
   3101 		glBindFragDataLocation(program, 0, "FragColor");
   3102 		glLinkProgram(program);
   3103 		if (!CheckProgram(program))
   3104 			return ERROR;
   3105 		glUseProgram(program);
   3106 
   3107 		glGenTextures(1, &tex);
   3108 		glBindTexture(GL_TEXTURE_2D, tex);
   3109 		std::vector<Vec4> data(100 * 100, Vec4(0.25, 0.5, 0.75, 1));
   3110 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 100, 100, 0, GL_RGBA, GL_FLOAT, &data[0]);
   3111 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   3112 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   3113 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
   3114 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
   3115 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
   3116 
   3117 		GLuint l_vao;
   3118 		glGenVertexArrays(1, &l_vao);
   3119 		glBindVertexArray(l_vao);
   3120 		glGenBuffers(1, &vbo);
   3121 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
   3122 		GLfloat buffData[16] = { -1, 1, 0, 1, -1, -1, 0, 1, 1, 1, 0, 1, 1, -1, 0, 1 };
   3123 		glBufferData(GL_ARRAY_BUFFER, sizeof(buffData), buffData, GL_STATIC_DRAW);
   3124 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0);
   3125 		glEnableVertexAttribArray(0);
   3126 		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   3127 		glDisableVertexAttribArray(0);
   3128 		glDeleteVertexArrays(1, &l_vao);
   3129 		glBindBuffer(GL_ARRAY_BUFFER, 0);
   3130 
   3131 		glReadBuffer(GL_COLOR_ATTACHMENT0);
   3132 		std::vector<Vec4> read(100 * 100, Vec4(0));
   3133 		glReadPixels(0, 0, 100, 100, GL_RGBA, GL_FLOAT, &read[0]);
   3134 		for (unsigned int i = 0; i < read.size(); ++i)
   3135 		{
   3136 			if (read[i] != Vec4(0.75))
   3137 			{
   3138 				m_context.getTestContext().getLog()
   3139 					<< tcu::TestLog::Message << "Got: " << read[i].x() << " " << read[i].y() << " " << read[i].z()
   3140 					<< " " << read[i].w() << ", expected vec4(0.25)" << tcu::TestLog::EndMessage;
   3141 				return ERROR;
   3142 			}
   3143 		}
   3144 
   3145 		return NO_ERROR;
   3146 	}
   3147 
   3148 	virtual long Cleanup()
   3149 	{
   3150 		glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
   3151 		glViewport(0, 0, GetWindowWidth(), GetWindowHeight());
   3152 		glDeleteTextures(1, &tex);
   3153 		glDeleteFramebuffers(1, &fbo);
   3154 		glDeleteRenderbuffers(1, &rbo);
   3155 		glDeleteVertexArrays(1, &vao);
   3156 		glDeleteBuffers(1, &vbo);
   3157 		glDeleteProgram(program);
   3158 		return NO_ERROR;
   3159 	}
   3160 };
   3161 
   3162 class PlainGatherFloat2DSrgb : public GatherBase
   3163 {
   3164 public:
   3165 	virtual Vec4 Expected()
   3166 	{
   3167 		return Vec4(0.f, 0.0512695f, 0.21582f, 0.519531f);
   3168 	}
   3169 
   3170 	virtual GLenum InternalFormat()
   3171 	{
   3172 		return GL_SRGB8_ALPHA8;
   3173 	}
   3174 };
   3175 
   3176 class PlainGatherFloat2DSrgbAlpha : public GatherBase
   3177 {
   3178 public:
   3179 	virtual std::string TestFunction()
   3180 	{
   3181 		return "uniform sampler2D my_sampler;                                   \n"
   3182 			   ""
   3183 			   "vec4 test_function(vec4 p) {                                    \n"
   3184 			   "    return textureGather(my_sampler, vec2(p.x, p.y), 3);        \n"
   3185 			   "}\n";
   3186 	}
   3187 
   3188 	virtual Vec4 Expected()
   3189 	{
   3190 		return Vec4(3. / 16, 7. / 16, 11. / 16, 15. / 16);
   3191 	}
   3192 
   3193 	virtual GLenum InternalFormat()
   3194 	{
   3195 		return GL_SRGB8_ALPHA8;
   3196 	}
   3197 };
   3198 
   3199 class GatherGeometryShader : public GatherBase
   3200 {
   3201 	virtual std::string VertexShader()
   3202 	{
   3203 		return "#version 400                       \n"
   3204 			   "in vec4 v_in_0;                    \n"
   3205 			   "out vec4 d;                        \n"
   3206 			   "void main() {                      \n"
   3207 			   "   gl_Position = vec4(0, 0, 0, 1); \n"
   3208 			   "   d = v_in_0;                     \n"
   3209 			   "}";
   3210 	};
   3211 
   3212 	virtual std::string GeometryShader()
   3213 	{
   3214 		return "#version 400                                                  \n"
   3215 			   "layout(points) in;                                            \n"
   3216 			   "layout(points, max_vertices = 1) out;                         \n"
   3217 			   "out vec4 col;                                                 \n"
   3218 			   "in vec4 d[1];                                                 \n"
   3219 			   "uniform sampler2D tex;                                        \n"
   3220 			   ""
   3221 			   "void main() {                                                 \n"
   3222 			   "   vec4 v1 = textureGather(tex, vec2(d[0].x, d[0].y));                                               \n"
   3223 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d[0].x, d[0].y) - vec2(4./32), ivec2(4));                 \n"
   3224 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));         \n"
   3225 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d[0].x, d[0].y) - vec2(5./32, 18./32), offsets);         \n"
   3226 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                \n"
   3227 			   "   float error = 0.0;                                         \n"
   3228 			   ""
   3229 			   "   if (v1 != expected)    \n"
   3230 			   "       error += 0.01;     \n"
   3231 			   "   if (v2 != expected)    \n"
   3232 			   "       error += 0.02;     \n"
   3233 			   "   if (v3 != expected)    \n"
   3234 			   "       error += 0.04;     \n"
   3235 			   ""
   3236 			   "   if (error != 0.0)                         \n"
   3237 			   "       col = vec4(v1.x, v2.y, v3.z, d[0].x); \n"
   3238 			   "   else                                      \n"
   3239 			   "       col = vec4(0, 1, 0, 1);               \n"
   3240 			   ""
   3241 			   "   gl_Position = vec4(0, 0, 0, 1);         \n"
   3242 			   "   EmitVertex();                           \n"
   3243 			   "   EndPrimitive();                         \n"
   3244 			   "}";
   3245 	}
   3246 
   3247 	virtual std::string FragmentShader()
   3248 	{
   3249 		return "#version 400               \n"
   3250 			   "in vec4 col;               \n"
   3251 			   "out vec4 f_out_0;          \n"
   3252 			   "void main() {              \n"
   3253 			   "   f_out_0 = col;          \n"
   3254 			   "}";
   3255 	}
   3256 
   3257 	virtual long Run()
   3258 	{
   3259 		if (!Supported())
   3260 			return NO_ERROR;
   3261 		Init();
   3262 
   3263 		glGenFramebuffers(1, &fbo);
   3264 		glGenRenderbuffers(1, &rbo);
   3265 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
   3266 		SetRbo();
   3267 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
   3268 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
   3269 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
   3270 		glDrawBuffers(1, &drawBuffer);
   3271 		GLfloat colorf[4] = { 0, 0, 0, 0 };
   3272 		glClearBufferfv(GL_COLOR, 0, colorf);
   3273 		glViewport(0, 0, 1, 1);
   3274 
   3275 		glGenVertexArrays(1, &vao);
   3276 		glBindVertexArray(vao);
   3277 		glGenBuffers(1, &vbo);
   3278 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
   3279 		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
   3280 		glEnableVertexAttribArray(0);
   3281 		Vec4 buffData = BufferData();
   3282 		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
   3283 
   3284 		program = CreateProgram(VertexShader().c_str(), NULL, NULL, GeometryShader().c_str(), FragmentShader().c_str());
   3285 		glBindAttribLocation(program, 0, "v_in_0");
   3286 		glBindFragDataLocation(program, 0, "f_out_0");
   3287 		glLinkProgram(program);
   3288 		if (!CheckProgram(program))
   3289 			return ERROR;
   3290 		glUseProgram(program);
   3291 
   3292 		glDrawArrays(GL_POINTS, 0, 1);
   3293 		glReadBuffer(GL_COLOR_ATTACHMENT0);
   3294 
   3295 		glDeleteProgram(program);
   3296 		Vec4 data;
   3297 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, &data);
   3298 		if (!ColorEqual(data, Vec4(0, 1, 0, 1), g_color_eps))
   3299 		{
   3300 			m_context.getTestContext().getLog()
   3301 				<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data.x() << ", " << data.y() << ", "
   3302 				<< data.z() << ", " << data.w() << ", epsilon: " << g_color_eps.x() << ", " << g_color_eps.y() << ", "
   3303 				<< g_color_eps.z() << ", " << g_color_eps.w() << tcu::TestLog::EndMessage;
   3304 			return ERROR;
   3305 		}
   3306 		return NO_ERROR;
   3307 	}
   3308 };
   3309 
   3310 class GatherTesselationShader : public GatherBase
   3311 {
   3312 	virtual std::string VertexShader()
   3313 	{
   3314 		return "#version 400               \n"
   3315 			   "in vec4 v_in_0;            \n"
   3316 			   "out vec4 d;                \n"
   3317 			   "void main() {              \n"
   3318 			   "   gl_Position = vec4(0, 0, 0, 1); \n"
   3319 			   "   d = v_in_0;             \n"
   3320 			   "}";
   3321 	}
   3322 
   3323 	virtual std::string ControlShader()
   3324 	{
   3325 		return "#version 400                                                  \n"
   3326 			   "layout(vertices = 1) out;                                     \n"
   3327 			   "out vec4 ccol[];                                              \n"
   3328 			   "in vec4 d[];                                                  \n"
   3329 			   "out vec4 d_con[];                                             \n"
   3330 			   "uniform sampler2D tex;                                        \n"
   3331 			   ""
   3332 			   "void main() {                                        \n"
   3333 			   "   vec4 v1 = textureGather(tex, vec2(d[0].x, d[0].y));                                               \n"
   3334 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d[0].x, d[0].y) - vec2(4./32), ivec2(4));                 \n"
   3335 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));         \n"
   3336 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d[0].x, d[0].y) - vec2(5./32, 18./32), offsets);         \n"
   3337 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                \n"
   3338 			   "   float error = 0.0;                                         \n"
   3339 			   ""
   3340 			   "   if (v1 != expected)    \n"
   3341 			   "       error += 0.01;     \n"
   3342 			   "   if (v2 != expected)    \n"
   3343 			   "       error += 0.02;     \n"
   3344 			   "   if (v3 != expected)    \n"
   3345 			   "       error += 0.04;     \n"
   3346 			   ""
   3347 			   "   if (error != 0.0)                                            \n"
   3348 			   "       ccol[gl_InvocationID] = vec4(v1.x, v2.y, d[0].x, 1);      \n"
   3349 			   "   else                                                         \n"
   3350 			   "       ccol[gl_InvocationID] = vec4(0, 1, 0, 1);                \n"
   3351 			   ""
   3352 			   "   d_con[gl_InvocationID] = d[gl_InvocationID];                                 \n"
   3353 			   "   gl_out[gl_InvocationID].gl_Position = vec4(0, 0, 0, 1);                      \n"
   3354 			   "   gl_TessLevelInner[0] = 1.0;                                                  \n"
   3355 			   "   gl_TessLevelOuter[0] = 1.0;                                                  \n"
   3356 			   "   gl_TessLevelOuter[1] = 1.0;                                                  \n"
   3357 			   "   gl_TessLevelOuter[2] = 1.0;                                                  \n"
   3358 			   "}";
   3359 	}
   3360 
   3361 	virtual std::string EvalShader()
   3362 	{
   3363 		return "#version 400                                                  \n"
   3364 			   "layout(triangles, point_mode) in;                             \n"
   3365 			   "in vec4 ccol[];                                               \n"
   3366 			   "in vec4 d_con[];                                              \n"
   3367 			   "out vec4 ecol;                                                \n"
   3368 			   "uniform sampler2D tex;                                        \n"
   3369 			   ""
   3370 			   "void main() {                                        \n"
   3371 			   "   vec4 v1 = textureGather(tex, vec2(d_con[0].x, d_con[0].y));                                         "
   3372 			   "      \n"
   3373 			   "   vec4 v2 = textureGatherOffset(tex, vec2(d_con[0].x, d_con[0].y) - vec2(4./32), ivec2(4));           "
   3374 			   "      \n"
   3375 			   "   const ivec2 offsets[4] = ivec2[](ivec2(7, 6), ivec2(-8, 7), ivec2(-6, -5), ivec2(-1, 3));           "
   3376 			   "      \n"
   3377 			   "   vec4 v3 = textureGatherOffsets(tex, vec2(d_con[0].x, d_con[0].y) - vec2(5./32, 18./32), offsets);   "
   3378 			   "      \n"
   3379 			   "   vec4 expected = vec4(0./16, 4./16, 8./16, 12./16);                                                  "
   3380 			   "      \n"
   3381 			   "   float error = 0.0;                                         \n"
   3382 			   ""
   3383 			   "   if (v1 != expected)    \n"
   3384 			   "       error += 0.01;     \n"
   3385 			   "   if (v2 != expected)    \n"
   3386 			   "       error += 0.02;     \n"
   3387 			   "   if (v3 != expected)    \n"
   3388 			   "       error += 0.04;     \n"
   3389 			   ""
   3390 			   "   if (error != 0.0)                                          \n"
   3391 			   "       ecol = vec4(v1.x, v2.y, d_con[0].x, -1);                      \n"
   3392 			   "   else if (ccol[0] != vec4(0, 1, 0, 1))     \n"
   3393 			   "       ecol = ccol[0];                       \n"
   3394 			   "   else                                      \n"
   3395 			   "       ecol = vec4(0, 1, 0, 1);              \n"
   3396 			   ""
   3397 			   "   gl_Position = vec4(0, 0, 0, 1);   \n"
   3398 			   "}";
   3399 	}
   3400 
   3401 	virtual std::string FragmentShader()
   3402 	{
   3403 		return "#version 400               \n"
   3404 			   "in vec4 ecol;              \n"
   3405 			   "out vec4 f_out_0;          \n"
   3406 			   "void main() {              \n"
   3407 			   "   f_out_0 = ecol;         \n"
   3408 			   "}";
   3409 	}
   3410 
   3411 	virtual long Run()
   3412 	{
   3413 
   3414 		if (!Supported())
   3415 			return NO_ERROR;
   3416 		Init();
   3417 
   3418 		glGenFramebuffers(1, &fbo);
   3419 		glGenRenderbuffers(1, &rbo);
   3420 		glBindRenderbuffer(GL_RENDERBUFFER, rbo);
   3421 		SetRbo();
   3422 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
   3423 		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
   3424 		GLenum drawBuffer = GL_COLOR_ATTACHMENT0;
   3425 		glDrawBuffers(1, &drawBuffer);
   3426 		GLfloat colorf[4] = { 0, 0, 0, 0 };
   3427 		glClearBufferfv(GL_COLOR, 0, colorf);
   3428 		glViewport(0, 0, 1, 1);
   3429 
   3430 		glGenVertexArrays(1, &vao);
   3431 		glBindVertexArray(vao);
   3432 		glGenBuffers(1, &vbo);
   3433 		glBindBuffer(GL_ARRAY_BUFFER, vbo);
   3434 		glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
   3435 		glEnableVertexAttribArray(0);
   3436 		Vec4 buffData = BufferData();
   3437 		glBufferData(GL_ARRAY_BUFFER, 16, &buffData, GL_STATIC_DRAW);
   3438 
   3439 		program = CreateProgram(VertexShader().c_str(), ControlShader().c_str(), EvalShader().c_str(), NULL,
   3440 								FragmentShader().c_str());
   3441 		glBindAttribLocation(program, 0, "v_in_0");
   3442 		glBindFragDataLocation(program, 0, "f_out_0");
   3443 		glLinkProgram(program);
   3444 		if (!CheckProgram(program))
   3445 			return ERROR;
   3446 		glUseProgram(program);
   3447 
   3448 		glPatchParameteri(GL_PATCH_VERTICES, 1);
   3449 		glDrawArrays(GL_PATCHES, 0, 1);
   3450 		glReadBuffer(GL_COLOR_ATTACHMENT0);
   3451 
   3452 		glDeleteProgram(program);
   3453 		Vec4 data;
   3454 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, &data);
   3455 		if (!ColorEqual(data, Vec4(0, 1, 0, 1), g_color_eps))
   3456 		{
   3457 			m_context.getTestContext().getLog()
   3458 				<< tcu::TestLog::Message << "Expected Vec4(0, 1, 0, 1), got: " << data.x() << ", " << data.y() << ", "
   3459 				<< data.z() << ", " << data.w() << ", epsilon: " << g_color_eps.x() << ", " << g_color_eps.y() << ", "
   3460 				<< g_color_eps.z() << ", " << g_color_eps.w() << tcu::TestLog::EndMessage;
   3461 			return ERROR;
   3462 		}
   3463 		return NO_ERROR;
   3464 	}
   3465 };
   3466 
   3467 class PlainGatherFloat2DRgb : public GatherBase
   3468 {
   3469 public:
   3470 	virtual void Init()
   3471 	{
   3472 		CreateTexture2DRgb();
   3473 	}
   3474 };
   3475 
   3476 class PlainGatherFloat2DR : public GatherBase
   3477 {
   3478 public:
   3479 	virtual void Init()
   3480 	{
   3481 		CreateTexture2DR();
   3482 	}
   3483 };
   3484 
   3485 class OffsetGatherFloat2DRgb : public OffsetGatherFloat2D
   3486 {
   3487 public:
   3488 	virtual void Init()
   3489 	{
   3490 		CreateTexture2DRgb();
   3491 	}
   3492 };
   3493 
   3494 class OffsetGatherFloat2DRg : public OffsetGatherFloat2D
   3495 {
   3496 public:
   3497 	virtual void Init()
   3498 	{
   3499 		CreateTexture2DRg();
   3500 	}
   3501 };
   3502 
   3503 class OffsetGatherFloat2DR : public OffsetGatherFloat2D
   3504 {
   3505 public:
   3506 	virtual void Init()
   3507 	{
   3508 		CreateTexture2DR();
   3509 	}
   3510 };
   3511 
   3512 } // anonymous namespace
   3513 
   3514 TextureGatherTests::TextureGatherTests(deqp::Context& context) : TestCaseGroup(context, "texture_gather", "")
   3515 {
   3516 }
   3517 
   3518 TextureGatherTests::~TextureGatherTests(void)
   3519 {
   3520 }
   3521 
   3522 void TextureGatherTests::init()
   3523 {
   3524 	using namespace deqp;
   3525 	addChild(new TestSubcase(m_context, "api-enums", TestSubcase::Create<GatherEnumsTest>));
   3526 	addChild(new TestSubcase(m_context, "gather-glsl-compile", TestSubcase::Create<GatherGLSLCompile>));
   3527 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgba", TestSubcase::Create<PlainGatherFloat2DRgba>));
   3528 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rg", TestSubcase::Create<PlainGatherFloat2DRg>));
   3529 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2d", TestSubcase::Create<PlainGatherUnorm2D>));
   3530 	addChild(new TestSubcase(m_context, "plain-gather-int-2d-rgba", TestSubcase::Create<PlainGatherInt2DRgba>));
   3531 	addChild(new TestSubcase(m_context, "plain-gather-int-2d-rg", TestSubcase::Create<PlainGatherInt2DRg>));
   3532 	addChild(new TestSubcase(m_context, "plain-gather-uint-2d", TestSubcase::Create<PlainGatherUint2D>));
   3533 	addChild(new TestSubcase(m_context, "plain-gather-depth-2d", TestSubcase::Create<PlainGatherDepth2D>));
   3534 	addChild(new TestSubcase(m_context, "plain-gather-float-2darray", TestSubcase::Create<PlainGatherFloat2DArray>));
   3535 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2darray", TestSubcase::Create<PlainGatherUnorm2DArray>));
   3536 	addChild(new TestSubcase(m_context, "plain-gather-int-2darray", TestSubcase::Create<PlainGatherInt2DArray>));
   3537 	addChild(new TestSubcase(m_context, "plain-gather-uint-2darray", TestSubcase::Create<PlainGatherUint2DArray>));
   3538 	addChild(new TestSubcase(m_context, "plain-gather-depth-2darray", TestSubcase::Create<PlainGatherDepth2DArray>));
   3539 	addChild(new TestSubcase(m_context, "plain-gather-float-cube-rgba", TestSubcase::Create<PlainGatherFloatCubeRgba>));
   3540 	addChild(new TestSubcase(m_context, "plain-gather-float-cube-rg", TestSubcase::Create<PlainGatherFloatCubeRg>));
   3541 	addChild(new TestSubcase(m_context, "plain-gather-unorm-cube", TestSubcase::Create<PlainGatherUnormCube>));
   3542 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-rgba", TestSubcase::Create<PlainGatherIntCubeRgba>));
   3543 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-rg", TestSubcase::Create<PlainGatherIntCubeRg>));
   3544 	addChild(new TestSubcase(m_context, "plain-gather-uint-cube", TestSubcase::Create<PlainGatherUintCube>));
   3545 	addChild(new TestSubcase(m_context, "plain-gather-depth-cube", TestSubcase::Create<PlainGatherDepthCube>));
   3546 	addChild(
   3547 		new TestSubcase(m_context, "plain-gather-float-cube-array", TestSubcase::Create<PlainGatherFloatCubeArray>));
   3548 	addChild(
   3549 		new TestSubcase(m_context, "plain-gather-unorm-cube-array", TestSubcase::Create<PlainGatherUnormCubeArray>));
   3550 	addChild(new TestSubcase(m_context, "plain-gather-int-cube-array", TestSubcase::Create<PlainGatherIntCubeArray>));
   3551 	addChild(new TestSubcase(m_context, "plain-gather-uint-cube-array", TestSubcase::Create<PlainGatherUintCubeArray>));
   3552 	addChild(
   3553 		new TestSubcase(m_context, "plain-gather-depth-cube-array", TestSubcase::Create<PlainGatherDepthCubeArray>));
   3554 	addChild(new TestSubcase(m_context, "plain-gather-float-2drect", TestSubcase::Create<PlainGatherFloat2DRect>));
   3555 	addChild(new TestSubcase(m_context, "plain-gather-unorm-2drect", TestSubcase::Create<PlainGatherUnorm2DRect>));
   3556 	addChild(new TestSubcase(m_context, "plain-gather-int-2drect", TestSubcase::Create<PlainGatherInt2DRect>));
   3557 	addChild(new TestSubcase(m_context, "plain-gather-uint-2drect", TestSubcase::Create<PlainGatherUint2DRect>));
   3558 	addChild(new TestSubcase(m_context, "plain-gather-depth-2drect", TestSubcase::Create<PlainGatherDepth2DRect>));
   3559 	addChild(new TestSubcase(m_context, "offset-gather-float-2d", TestSubcase::Create<OffsetGatherFloat2D>));
   3560 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2d", TestSubcase::Create<OffsetGatherUnorm2D>));
   3561 	addChild(new TestSubcase(m_context, "offset-gather-int-2d", TestSubcase::Create<OffsetGatherInt2D>));
   3562 	addChild(new TestSubcase(m_context, "offset-gather-uint-2d", TestSubcase::Create<OffsetGatherUint2D>));
   3563 	addChild(new TestSubcase(m_context, "offset-gather-depth-2d", TestSubcase::Create<OffsetGatherDepth2D>));
   3564 	addChild(new TestSubcase(m_context, "offset-gather-float-2darray", TestSubcase::Create<OffsetGatherFloat2DArray>));
   3565 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2darray", TestSubcase::Create<OffsetGatherUnorm2DArray>));
   3566 	addChild(new TestSubcase(m_context, "offset-gather-int-2darray", TestSubcase::Create<OffsetGatherInt2DArray>));
   3567 	addChild(new TestSubcase(m_context, "offset-gather-uint-2darray", TestSubcase::Create<OffsetGatherUint2DArray>));
   3568 	addChild(new TestSubcase(m_context, "offset-gather-depth-2darray", TestSubcase::Create<OffsetGatherDepth2DArray>));
   3569 	addChild(new TestSubcase(m_context, "offset-gather-float-2drect", TestSubcase::Create<OffsetGatherFloat2DRect>));
   3570 	addChild(new TestSubcase(m_context, "offset-gather-unorm-2drect", TestSubcase::Create<OffsetGatherUnorm2DRect>));
   3571 	addChild(new TestSubcase(m_context, "offset-gather-int-2drect", TestSubcase::Create<OffsetGatherInt2DRect>));
   3572 	addChild(new TestSubcase(m_context, "offset-gather-uint-2drect", TestSubcase::Create<OffsetGatherUint2DRect>));
   3573 	addChild(new TestSubcase(m_context, "offset-gather-depth-2drect", TestSubcase::Create<OffsetGatherDepth2DRect>));
   3574 	addChild(new TestSubcase(m_context, "offsets-gather-float-2d", TestSubcase::Create<OffsetsGatherFloat2D>));
   3575 	addChild(new TestSubcase(m_context, "offsets-gather-unorm-2d", TestSubcase::Create<OffsetsGatherUnorm2D>));
   3576 	addChild(new TestSubcase(m_context, "offsets-gather-int-2d", TestSubcase::Create<OffsetsGatherInt2D>));
   3577 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2d", TestSubcase::Create<OffsetsGatherUint2D>));
   3578 	addChild(new TestSubcase(m_context, "offsets-gather-depth-2d", TestSubcase::Create<OffsetsGatherDepth2D>));
   3579 	addChild(
   3580 		new TestSubcase(m_context, "offsets-gather-float-2darray", TestSubcase::Create<OffsetsGatherFloat2DArray>));
   3581 	addChild(
   3582 		new TestSubcase(m_context, "offsets-gather-unorm-2darray", TestSubcase::Create<OffsetsGatherUnorm2DArray>));
   3583 	addChild(new TestSubcase(m_context, "offsets-gather-int-2darray", TestSubcase::Create<OffsetsGatherInt2DArray>));
   3584 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2darray", TestSubcase::Create<OffsetsGatherUint2DArray>));
   3585 	addChild(
   3586 		new TestSubcase(m_context, "offsets-gather-depth-2darray", TestSubcase::Create<OffsetsGatherDepth2DArray>));
   3587 	addChild(new TestSubcase(m_context, "offsets-gather-float-2drect", TestSubcase::Create<OffsetsGatherFloat2DRect>));
   3588 	addChild(new TestSubcase(m_context, "offsets-gather-unorm-2drect", TestSubcase::Create<OffsetsGatherUnorm2DRect>));
   3589 	addChild(new TestSubcase(m_context, "offsets-gather-int-2drect", TestSubcase::Create<OffsetsGatherInt2DRect>));
   3590 	addChild(new TestSubcase(m_context, "offsets-gather-uint-2drect", TestSubcase::Create<OffsetsGatherUint2DRect>));
   3591 	addChild(new TestSubcase(m_context, "offsets-gather-depth-2drect", TestSubcase::Create<OffsetsGatherDepth2DRect>));
   3592 	addChild(new TestSubcase(m_context, "swizzle", TestSubcase::Create<Swizzle>));
   3593 	addChild(new TestSubcase(m_context, "base-level", TestSubcase::Create<BaseLevel>));
   3594 	addChild(new TestSubcase(m_context, "incomplete-texture", TestSubcase::Create<IncompleteTexture>));
   3595 	addChild(
   3596 		new TestSubcase(m_context, "incomplete-texture-last-comp", TestSubcase::Create<IncompleteTextureLastComp>));
   3597 	addChild(new TestSubcase(m_context, "triangle-draw", TestSubcase::Create<TriangleDraw>));
   3598 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb", TestSubcase::Create<PlainGatherFloat2DSrgb>));
   3599 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-srgb-alpha",
   3600 							 TestSubcase::Create<PlainGatherFloat2DSrgbAlpha>));
   3601 	addChild(new TestSubcase(m_context, "gather-geometry-shader", TestSubcase::Create<GatherGeometryShader>));
   3602 	addChild(new TestSubcase(m_context, "gather-tesselation-shader", TestSubcase::Create<GatherTesselationShader>));
   3603 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-rgb", TestSubcase::Create<PlainGatherFloat2DRgb>));
   3604 	addChild(new TestSubcase(m_context, "plain-gather-float-2d-r", TestSubcase::Create<PlainGatherFloat2DR>));
   3605 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rgb", TestSubcase::Create<OffsetGatherFloat2DRgb>));
   3606 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-rg", TestSubcase::Create<OffsetGatherFloat2DRg>));
   3607 	addChild(new TestSubcase(m_context, "offset-gather-float-2d-r", TestSubcase::Create<OffsetGatherFloat2DR>));
   3608 }
   3609 
   3610 } // gl4cts namespace
   3611