Home | History | Annotate | Download | only in gpu_shader5
      1 #ifndef _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
      2 #define _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
      3 /*-------------------------------------------------------------------------
      4  * OpenGL Conformance Test Suite
      5  * -----------------------------
      6  *
      7  * Copyright (c) 2014-2016 The Khronos Group Inc.
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  */ /*!
     22  * \file
     23  * \brief
     24  */ /*-------------------------------------------------------------------*/
     25 
     26 /*!
     27  * \file esextcGPUShader5TextureGatherOffset.hpp
     28  * \brief gpu_shader5 extension - texture gather offset tests (Test 9 and 10)
     29  */ /*-------------------------------------------------------------------*/
     30 
     31 #include "../esextcTestCaseBase.hpp"
     32 
     33 #include <string>
     34 #include <vector>
     35 
     36 namespace glcts
     37 {
     38 /** Base class for texture gather offset tests (9, 10 and 11)
     39  *
     40  **/
     41 class GPUShader5TextureGatherOffsetTestBase : public TestCaseBase
     42 {
     43 public:
     44 	/* Public methods */
     45 	virtual void		  deinit(void);
     46 	virtual IterateResult iterate(void);
     47 
     48 protected:
     49 	/* Protected types */
     50 	struct VertexBufferInfo
     51 	{
     52 		const glw::GLchar* attribute_name;
     53 		glw::GLuint		   n_components;
     54 		glw::GLenum		   type;
     55 		glw::GLvoid*	   data;
     56 		glw::GLuint		   data_size;
     57 	};
     58 
     59 	/* Protected methods */
     60 	GPUShader5TextureGatherOffsetTestBase(Context& context, const ExtParameters& extParams, const char* name,
     61 										  const char* description);
     62 
     63 	virtual ~GPUShader5TextureGatherOffsetTestBase(void)
     64 	{
     65 	}
     66 
     67 	virtual void initTest(void);
     68 
     69 	/* To be implemented by inheriting classes */
     70 	virtual void getBorderColor(glw::GLfloat out_color[4])								  = 0;
     71 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts) = 0;
     72 
     73 	virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format,
     74 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
     75 								glw::GLuint& out_bytes_per_pixel) = 0;
     76 
     77 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode) = 0;
     78 
     79 	virtual void getTransformFeedBackDetails(glw::GLuint&					  buffer_size,
     80 											 std::vector<const glw::GLchar*>& captured_varyings) = 0;
     81 
     82 	virtual void isTextureArray(bool& out_is_texture_array)									  = 0;
     83 	virtual void prepareTextureData(glw::GLubyte* data)										  = 0;
     84 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos) = 0;
     85 	virtual bool verifyResult(const void* result_data)										  = 0;
     86 
     87 	/* Utilities */
     88 	void logArray(const glw::GLint* data, unsigned int length, const char* description);
     89 
     90 	void logCoordinates(unsigned int index);
     91 
     92 	/* Protected fields */
     93 	/* GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET and GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET pname values */
     94 	glw::GLint m_min_texture_gather_offset;
     95 	glw::GLint m_max_texture_gather_offset;
     96 
     97 	/* Number of drawn vertices */
     98 	static const unsigned int m_n_vertices;
     99 
    100 	/* Number of components in captured varyings */
    101 	static const unsigned int m_n_components_per_varying;
    102 
    103 private:
    104 	/* Private methods */
    105 	void prepareProgramInput();
    106 	void prepareTexture();
    107 	void prepareVertexBufferInfoForCoordinates();
    108 	void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, unsigned int index);
    109 	void setCoordinatesData(glw::GLfloat x, glw::GLfloat y, glw::GLfloat z, unsigned int index);
    110 
    111 	/* Private fields */
    112 	/* Program and shader ids */
    113 	glw::GLuint m_fragment_shader_id;
    114 	glw::GLuint m_program_object_id;
    115 	glw::GLuint m_vertex_shader_id;
    116 
    117 	/* Vertex array object */
    118 	glw::GLuint m_vertex_array_object_id;
    119 
    120 	/* Texture id */
    121 	glw::GLuint m_texture_object_id;
    122 
    123 	/* Sampler id */
    124 	glw::GLuint m_sampler_object_id;
    125 
    126 	/* Shaders' code */
    127 	static const glw::GLchar* const m_fragment_shader_code;
    128 	std::vector<const glw::GLchar*> m_vertex_shader_parts;
    129 
    130 	/* Name of uniforms */
    131 	static const glw::GLchar* const m_sampler_uniform_name;
    132 	static const glw::GLchar* const m_reference_sampler_uniform_name;
    133 
    134 	/* Vertex buffer infos */
    135 	std::vector<VertexBufferInfo> m_vertex_buffer_infos;
    136 	std::vector<glw::GLuint>	  m_vertex_buffer_ids;
    137 
    138 	/* Texture info */
    139 	bool		m_is_texture_array;
    140 	glw::GLuint m_texture_bytes_per_pixel;
    141 	glw::GLenum m_texture_format;
    142 	glw::GLenum m_texture_internal_format;
    143 	glw::GLenum m_texture_type;
    144 	glw::GLuint m_texture_size;
    145 	glw::GLenum m_texture_wrap_mode;
    146 
    147 	/* Texture array length */
    148 	static const unsigned int m_n_texture_array_length;
    149 
    150 	/* Name of varyings */
    151 	std::vector<const glw::GLchar*> m_captured_varying_names;
    152 
    153 	/* Size of buffer used for transform feedback */
    154 	glw::GLuint m_transform_feedback_buffer_size;
    155 
    156 	/* Buffer object used in transform feedback */
    157 	glw::GLuint m_transform_feedback_buffer_object_id;
    158 
    159 	/* Storage for texture coordinates */
    160 	std::vector<glw::GLfloat> m_coordinates_buffer_data;
    161 
    162 	/* Number of texture coordinates per vertex */
    163 	unsigned int m_n_coordinates_components;
    164 
    165 	/* Name of texture coordinate attribute */
    166 	static const glw::GLchar* const m_coordinates_attribute_name;
    167 
    168 	/* Configuration of texture coordinate values generation */
    169 	static const int m_max_coordinate_value;
    170 	static const int m_min_coordinate_value;
    171 	static const int m_coordinate_resolution;
    172 };
    173 
    174 /** Base class for test 9 and 11
    175  *
    176  **/
    177 class GPUShader5TextureGatherOffsetColorTestBase : public GPUShader5TextureGatherOffsetTestBase
    178 {
    179 protected:
    180 	/* Protected types */
    181 	struct CapturedVaryings
    182 	{
    183 		glw::GLint without_offset_0[4];
    184 		glw::GLint without_offset_1[4];
    185 		glw::GLint without_offset_2[4];
    186 		glw::GLint without_offset_3[4];
    187 
    188 		glw::GLint with_offset_0[4];
    189 		glw::GLint with_offset_1[4];
    190 		glw::GLint with_offset_2[4];
    191 		glw::GLint with_offset_3[4];
    192 	};
    193 
    194 	/* Protected methods */
    195 	GPUShader5TextureGatherOffsetColorTestBase(Context& context, const ExtParameters& extParams, const char* name,
    196 											   const char* description);
    197 
    198 	virtual ~GPUShader5TextureGatherOffsetColorTestBase(void)
    199 	{
    200 	}
    201 
    202 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    203 	virtual void getBorderColor(glw::GLfloat out_color[4]);
    204 
    205 	virtual void getTextureInfo(glw::GLuint& out_size, glw::GLenum& out_texture_internal_format,
    206 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
    207 								glw::GLuint& out_bytes_per_pixel);
    208 
    209 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
    210 
    211 	virtual void getTransformFeedBackDetails(glw::GLuint&					  out_buffer_size,
    212 											 std::vector<const glw::GLchar*>& out_captured_varyings);
    213 
    214 	virtual void isTextureArray(bool& out_is_texture_array);
    215 	virtual void prepareTextureData(glw::GLubyte* data);
    216 	virtual bool verifyResult(const void* result_data);
    217 
    218 	/* Methods to be implemented by child classes */
    219 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index,
    220 							 unsigned int m_texture_size) = 0;
    221 
    222 	/* Utilities */
    223 	void logVaryings(const CapturedVaryings& varyings);
    224 
    225 private:
    226 	/* Texture size */
    227 	static const glw::GLuint m_texture_size;
    228 
    229 	/* Number of varyings captured per vertex */
    230 	unsigned int m_n_varyings_per_vertex;
    231 };
    232 
    233 /** Base class for test 10 and 11
    234  *
    235  **/
    236 class GPUShader5TextureGatherOffsetDepthTestBase : public GPUShader5TextureGatherOffsetTestBase
    237 {
    238 protected:
    239 	/* Protected types */
    240 	struct CapturedVaryings
    241 	{
    242 		glw::GLint floor_tex_coord[4];
    243 		glw::GLint without_offset[4];
    244 		glw::GLint with_offset[4];
    245 	};
    246 
    247 	/* Protected methods */
    248 	GPUShader5TextureGatherOffsetDepthTestBase(Context& context, const ExtParameters& extParams, const char* name,
    249 											   const char* description);
    250 
    251 	virtual ~GPUShader5TextureGatherOffsetDepthTestBase(void)
    252 	{
    253 	}
    254 
    255 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    256 	virtual void getBorderColor(glw::GLfloat out_color[4]);
    257 
    258 	virtual void getTextureInfo(glw::GLuint& out_width, glw::GLenum& out_texture_internal_format,
    259 								glw::GLenum& out_texture_format, glw::GLenum& out_texture_type,
    260 								glw::GLuint& out_bytes_per_pixel);
    261 
    262 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
    263 
    264 	virtual void getTransformFeedBackDetails(glw::GLuint&					  out_buffer_size,
    265 											 std::vector<const glw::GLchar*>& out_captured_varyings);
    266 
    267 	virtual void isTextureArray(bool& out_is_texture_array);
    268 	virtual void prepareTextureData(glw::GLubyte* data);
    269 	virtual bool verifyResult(const void* result_data);
    270 
    271 	/* Methods to be implemented by child classes */
    272 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size) = 0;
    273 
    274 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
    275 
    276 	/* Utilities */
    277 	void logVaryings(const CapturedVaryings& varyings);
    278 
    279 private:
    280 	/* Texture size */
    281 	static const glw::GLuint m_texture_size;
    282 
    283 	/* Number of varyings captured per vertex */
    284 	unsigned int m_n_varyings_per_vertex;
    285 };
    286 
    287 /** Implementation of "Test 9" from CTS_EXT_gpu_shader5. Test description follows:
    288  *
    289  *  Test whether using non constant offsets in the textureGatherOffset
    290  *  and constant offsets in the textureGatherOffsets family of
    291  *  functions works as expected for sampler2D and sampler2DArray and
    292  *  GL_REPEAT wrap mode.
    293  *
    294  *  Category:   API,
    295  *              Functional Test.
    296  *
    297  *  Create a 64 x 64 texture with internal format GL_RGBA32I.
    298  *
    299  *  Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST.
    300  *
    301  *  Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT.
    302  *
    303  *  Fill the 4 components of each texel with values corresponding to texel
    304  *  row and column number (x,y) -> (x,y,x,y)
    305  *
    306  *  Write a vertex shader that defines:
    307  *
    308  *  uniform isampler2D sampler;
    309  *
    310  *  in ivec2 tgoOffset;
    311  *  in  vec2 texCoords;
    312  *
    313  *  out ivec4 withoutOffset0;
    314  *  out ivec4 withOffset0;
    315  *
    316  *  out ivec4 withoutOffset1;
    317  *  out ivec4 withOffset1;
    318  *
    319  *  out ivec4 withoutOffset2;
    320  *  out ivec4 withOffset2;
    321  *
    322  *  out ivec4 withoutOffset3;
    323  *  out ivec4 withOffset3;
    324  *
    325  *  Bind the sampler to texture unit the texture we created is assigned to.
    326  *
    327  *  Initialize a buffer object to be assigned as input attribute tgoOffset
    328  *  data source. The buffer object should hold 128 integer tuples. Fill it
    329  *  with some random integer values but falling into a range of
    330  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
    331  *   MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
    332  *
    333  *  Initialize a buffer object to be assigned as input attribute texCoords
    334  *  data source. The buffer object should hold 128 elements. Fill the first
    335  *  4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
    336  *  rest with some random float values in the range [-8.0..8.0].
    337  *
    338  *  In the vertex shader perform the following operation:
    339  *
    340  *  withoutOffset0 = textureGather(sampler, texCoords, 0);
    341  *  withOffset0 = textureGatherOffset(sampler, texCoords, tgoOffset, 0);
    342  *
    343  *  withoutOffset1 = textureGather(sampler, texCoords, 1);
    344  *  withOffset1 = textureGatherOffset(sampler, texCoords, tgoOffset, 1);
    345  *
    346  *  withoutOffset2 = textureGather(sampler, texCoords, 2);
    347  *  withOffset2 = textureGatherOffset(sampler, texCoords, tgoOffset, 2);
    348  *
    349  *  withoutOffset3 = textureGather(sampler, texCoords, 3);
    350  *  withOffset3 = textureGatherOffset(sampler, texCoords, tgoOffset, 3);
    351  *
    352  *  Configure transform feedback to capture the values of withoutOffset*
    353  *  and withOffset*.
    354  *
    355  *  Write a boilerplate fragment shader.
    356  *
    357  *  Create a program from the above vertex shader and fragment shader
    358  *  and use it.
    359  *
    360  *  Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
    361  *
    362  *  Copy the captured results from the buffer objects bound to transform
    363  *  feedback binding points.
    364  *
    365  *  Using the captured values for each of the 128 results compute
    366  *
    367  *  (Pseudocode)
    368  *
    369  *  i = 0...127
    370  *
    371  *  ivec2 referenceOffset = offsets[i];
    372  *
    373  *  if(referenceOffset[0] < 0 )
    374  *  {
    375  *      referenceOffset[0] = sizeX - (referenceOffset[0] % sizeX);
    376  *  }
    377  *  if(referenceOffset[1] < 0 )
    378  *  {
    379  *      referenceOffset[1] = sizeY - (referenceOffset[1] % sizeY);
    380  *  }
    381  *
    382  *  for(int tNr = 0 tNr < 4; ++tNr)
    383  *  {
    384  *      ivec2 referenceTexelValue01 = ivec2(
    385  *       ((tgoResults[i].withoutOffset0[tNr] + referenceOffset[0]) % sizeX),
    386  *       ((tgoResults[i].withoutOffset1[tNr] + referenceOffset[1]) % sizeY));
    387  *
    388  *      ivec2 referenceTexelValue23 = ivec2(
    389  *       ((tgoResults[i].withoutOffset2[tNr] + referenceOffset[0]) % sizeX),
    390  *       ((tgoResults[i].withoutOffset3[tNr] + referenceOffset[1]) % sizeY));
    391  *
    392  *      ivec2 texelValue01 = ivec2(
    393  *       tgoResults[i].withOffset0[tNr], tgoResults[i].withOffset1[tNr]);
    394  *
    395  *      ivec2 texelValue23 = ivec2(
    396  *       tgoResults[i].withOffset2[tNr], tgoResults[i].withOffset3[tNr]);
    397  *  }
    398  *
    399  *  The test passes if in all cases we have
    400  *  referenceTexelValue01 == texelValue01 and
    401  *  referenceTexelValue23 == texelValue23.
    402  *
    403  *  Repeat the same type of test for sampler2DArray.
    404  *
    405  *  Repeat the same type of test using textureGatherOffsets instead of
    406  *  textureGatherOffset inputing constant offsets
    407  *  offsets[4] = {
    408  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
    409  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET),
    410  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
    411  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET, MAX_PROGRAM_TEXTURE_GATHER_OFFSET)
    412  *  };
    413  **/
    414 
    415 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffset
    416  */
    417 class GPUShader5TextureGatherOffsetColor2DRepeatCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
    418 {
    419 public:
    420 	/* Public methods */
    421 	GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
    422 													   const char* name, const char* description);
    423 
    424 	virtual ~GPUShader5TextureGatherOffsetColor2DRepeatCaseTest(void)
    425 	{
    426 	}
    427 
    428 protected:
    429 	/* Protected methods */
    430 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    431 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    432 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
    433 
    434 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
    435 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    436 
    437 	/* Utilities */
    438 	void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index);
    439 
    440 private:
    441 	/* Private fields */
    442 	/* Vertex shader code */
    443 	static const glw::GLchar* const m_vertex_shader_code;
    444 
    445 	/* Number of offsets per vertex */
    446 	static const unsigned int m_n_offsets_components;
    447 
    448 	/* Name of offset attribute */
    449 	static const glw::GLchar* const m_offsets_attribute_name;
    450 
    451 	/* Storage for offsets */
    452 	std::vector<glw::GLint> m_offsets_buffer_data;
    453 };
    454 
    455 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DArray, function textureGatherOffset
    456  */
    457 class GPUShader5TextureGatherOffsetColor2DArrayCaseTest : public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
    458 {
    459 public:
    460 	/* Public methods */
    461 	GPUShader5TextureGatherOffsetColor2DArrayCaseTest(Context& context, const ExtParameters& extParams,
    462 													  const char* name, const char* description);
    463 
    464 	virtual ~GPUShader5TextureGatherOffsetColor2DArrayCaseTest(void)
    465 	{
    466 	}
    467 
    468 protected:
    469 	/* Protected methods */
    470 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    471 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    472 	virtual void isTextureArray(bool& out_is_texture_array);
    473 
    474 private:
    475 	/* Private fields */
    476 	/* Vertex shader code */
    477 	static const glw::GLchar* const m_vertex_shader_code;
    478 };
    479 
    480 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2D, function textureGatherOffsets
    481  */
    482 class GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetColorTestBase
    483 {
    484 public:
    485 	/* Public methods */
    486 	GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
    487 														const char* name, const char* description);
    488 
    489 	virtual ~GPUShader5TextureGatherOffsetColor2DOffsetsCaseTest(void)
    490 	{
    491 	}
    492 
    493 protected:
    494 	/* Protected methods */
    495 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    496 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    497 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
    498 
    499 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
    500 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    501 
    502 private:
    503 	/* Private fields */
    504 	/* Vertex shader code */
    505 	static const glw::GLchar* const m_vertex_shader_code_preamble;
    506 	static const glw::GLchar* const m_vertex_shader_code_body;
    507 
    508 	/* String used for definition of constant offsets */
    509 	std::string m_vertex_shader_code_offsets;
    510 };
    511 
    512 /** Implementation of "Test 10" from CTS_EXT_gpu_shader5. Test description follows:
    513  *
    514  *  Test whether using non constant offsets in the textureGatherOffset
    515  *  and constant offsets in the textureGatherOffsets family of
    516  *  functions works as expected for sampler2DShadow
    517  *  and sampler2DArrayShadow and GL_REPEAT wrap mode.
    518  *
    519  *  Category:   API,
    520  *              Functional Test.
    521  *
    522  *  Create a 64 x 64 texture with internal format GL_DEPTH_COMPONENT and
    523  *  type GL_FLOAT.
    524  *
    525  *  Set both GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER to GL_NEAREST.
    526  *
    527  *  Set both GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T to GL_REPEAT.
    528  *
    529  *  Setup the texture parameters
    530  *
    531  *  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
    532  *                  COMPARE_REF_TO_TEXTURE);
    533  *
    534  *  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
    535  *
    536  *  Fill each texel with depth value corresponding to its position
    537  *  in the texture for the X axis: (x, y) -> (x / sizeX);
    538  *
    539  *  Write a vertex shader that defines:
    540  *
    541  *  uniform sampler2DShadow sampler;
    542  *
    543  *  in ivec2 tgoOffset;
    544  *  in  vec2 texCoords;
    545  *
    546  *  out ivec4 withoutOffset;
    547  *  out ivec4 withOffset;
    548  *
    549  *  Bind the sampler to texture unit the texture we created is assigned to.
    550  *
    551  *  Initialize a buffer object to be assigned as input attribute tgoOffset
    552  *  data source. The buffer object should hold 128 integer tuples. Fill it
    553  *  with some random integer values but falling into a range of
    554  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
    555  *   MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
    556  *
    557  *  Initialize a buffer object to be assigned as input attribute texCoords
    558  *  data source. The buffer object should hold 128 elements. Fill the first
    559  *  4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
    560  *  rest with some random float values in the range [-8.0..8.0].
    561  *
    562  *  In the vertex shader perform the following operation:
    563  *
    564  *  withoutOffset = ivec4(0,0,0,0);
    565  *  withOffset    = ivec4(0,0,0,0);
    566  *
    567  *  ivec2 texSize = textureSize2D(sampler, 0);
    568  *
    569  *  for(int texelNr = 0 texelNr < texSize.x; ++texelNr)
    570  *  {
    571  *      float refZ =  float(texelNr) / float(texSize.x);
    572  *
    573  *      withoutOffset += textureGather( sampler, texCoords, refZ );
    574  *      withOffset += textureGatherOffset(sampler,texCoords,offset,refZ);
    575  *  }
    576  *
    577  *  Configure transform feedback to capture the values of withoutOffset
    578  *  and withOffset.
    579  *
    580  *  Write a boilerplate fragment shader.
    581  *
    582  *  Create a program from the above vertex shader and fragment shader
    583  *  and use it.
    584  *
    585  *  Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
    586  *
    587  *  Copy the captured results from the buffer objects bound to transform
    588  *  feedback binding points.
    589  *
    590  *  Using the captured values for each of the 128 results compute
    591  *
    592  *  (Pseudocode)
    593  *
    594  *  i = 0...127
    595  *
    596  *  int referenceOffsetX = offsets[i].x;
    597  *
    598  *  if(referenceOffsetX < 0 )
    599  *  {
    600  *      referenceOffsetX = sizeX - (referenceOffsetX % sizeX);
    601  *  }
    602  *
    603  *  for(int tNr = 0 tNr < 4; ++tNr)
    604  *  {
    605  *      int referenceTexelValueX =
    606  *       (tgoResults[i].withoutOffset[tNr] + referenceOffsetX) % sizeX;
    607  *
    608  *      int texelValueX = tgoResults[i].withOffset[tNr];
    609  *  }
    610  *
    611  *  The test passes if in all cases we have
    612  *  referenceTexelValueX == texelValueX.
    613  *
    614  *  Repeat the same test for Y axis.
    615  *
    616  *  Repeat the same type of test for sampler2DArrayShadow.
    617  *
    618  *  Repeat the same type of test using textureGatherOffsets instead of
    619  *  textureGatherOffset inputting constant offsets
    620  *  offsets[4] = {
    621  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
    622  *  (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET),
    623  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MIN_PROGRAM_TEXTURE_GATHER_OFFSET),
    624  *  (MAX_PROGRAM_TEXTURE_GATHER_OFFSET,MAX_PROGRAM_TEXTURE_GATHER_OFFSET)
    625  *  };
    626  *
    627  **/
    628 
    629 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis X
    630  */
    631 class GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
    632 {
    633 public:
    634 	/* Public methods */
    635 	GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(Context& context, const ExtParameters& extParams,
    636 													   const char* name, const char* description);
    637 
    638 	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest(void)
    639 	{
    640 	}
    641 
    642 protected:
    643 	/* Protected methods */
    644 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    645 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    646 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
    647 
    648 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
    649 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    650 
    651 	/* Utilities */
    652 	void getOffsets(glw::GLint& out_x_offset, glw::GLint& out_y_offset, unsigned int index);
    653 
    654 	/* Number of offsets per vertex */
    655 	static const unsigned int m_n_offsets_components;
    656 
    657 	/* Name of offset attribute */
    658 	static const glw::GLchar* const m_offsets_attribute_name;
    659 
    660 	/* Storage for offsets */
    661 	std::vector<glw::GLint> m_offsets_buffer_data;
    662 
    663 private:
    664 	/* Private fields */
    665 	/* Vertex shader code */
    666 	static const glw::GLchar* const m_vertex_shader_code;
    667 };
    668 
    669 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffset, axis Y
    670  */
    671 class GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
    672 {
    673 public:
    674 	/* Public methods */
    675 	GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(Context& context, const ExtParameters& extParams,
    676 														const char* name, const char* description);
    677 
    678 	virtual ~GPUShader5TextureGatherOffsetDepth2DRepeatYCaseTest(void)
    679 	{
    680 	}
    681 
    682 protected:
    683 	/* Protected methods */
    684 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    685 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    686 	virtual void prepareTextureData(glw::GLubyte* data);
    687 
    688 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
    689 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    690 
    691 private:
    692 	/* Private fields */
    693 	/* Vertex shader code */
    694 	static const glw::GLchar* const m_vertex_shader_code;
    695 };
    696 
    697 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadowArray, function textureGatherOffset, axis X
    698  */
    699 class GPUShader5TextureGatherOffsetDepth2DArrayCaseTest : public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
    700 {
    701 public:
    702 	/* Public methods */
    703 	GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(Context& context, const ExtParameters& extParams,
    704 													  const char* name, const char* description);
    705 
    706 	virtual ~GPUShader5TextureGatherOffsetDepth2DArrayCaseTest(void)
    707 	{
    708 	}
    709 
    710 protected:
    711 	/* Protected methods */
    712 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    713 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    714 	virtual void isTextureArray(bool& out_is_texture_array);
    715 
    716 private:
    717 	/* Private fields */
    718 	/* Vertex shader code */
    719 	static const glw::GLchar* const m_vertex_shader_code;
    720 };
    721 
    722 /** Test configuration: wrap mode GL_REPEAT, sampler isampler2DShadow, function textureGatherOffsets, axis X
    723  */
    724 class GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest : public GPUShader5TextureGatherOffsetDepthTestBase
    725 {
    726 public:
    727 	/* Public methods */
    728 	GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(Context& context, const ExtParameters& extParams,
    729 														const char* name, const char* description);
    730 
    731 	virtual ~GPUShader5TextureGatherOffsetDepth2DOffsetsCaseTest(void)
    732 	{
    733 	}
    734 
    735 protected:
    736 	/* Protected methods */
    737 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    738 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    739 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
    740 
    741 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
    742 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    743 
    744 private:
    745 	/* Private fields */
    746 	/* Vertex shader code */
    747 	static const glw::GLchar* const m_vertex_shader_code_preamble;
    748 	static const glw::GLchar* const m_vertex_shader_code_body;
    749 
    750 	/* String used for definition of constant offsets */
    751 	std::string m_vertex_shader_code_offsets;
    752 };
    753 
    754 /** Implementation of "Test 11" from CTS_EXT_gpu_shader5. Test description follows:
    755  *
    756  * Test whether using non constant offsets in the textureGatherOffset
    757  * function works as expected for sampler2D and CLAMP_TO_BORDER_EXT
    758  * ( CLAMP_TO_EDGE ) wrap mode.
    759  *
    760  * Category:   API,
    761  *             Functional Test,
    762  *             dependency with EXT_texture_border_clamp.
    763  *
    764  * Create two (lets name them A and B) 64 (texWidth) x 64 (texHeight)
    765  * textures with internal format GL_RGBA32I.
    766  *
    767  * Bind texture A to texture unit 0.
    768  * Bind texture B to texture unit 1.
    769  *
    770  * Set for both textures GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER
    771  * to GL_NEAREST.
    772  *
    773  * For the A texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T
    774  * to CLAMP_TO_BORDER_EXT.
    775  * For the B texture set GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T
    776  * to CLAMP_TO_BORDER_EXT ( CLAMP TO EDGE ).
    777  *
    778  * For both textures fill the 4 components of each texel with values
    779  * corresponding to texel row and column number (x,y) -> (x,y,x,y)
    780  *
    781  * Set the GL_TEXTURE_BORDER_COLOR_EXT to (-1,-1,-1,-1).
    782  *
    783  * Write a vertex shader that defines:
    784  *
    785  * uniform isampler2D samplerWithoutOffset;
    786  * uniform isampler2D samplerWithOffset;
    787  *
    788  * in ivec2 tgoOffset;
    789  * in  vec2 texCoords;
    790  *
    791  * out ivec4 withoutOffset0;
    792  * out ivec4 withoutOffset1;
    793  * out ivec2 intFloorTexCoords;
    794  *
    795  * out ivec4 withOffset0;
    796  * out ivec4 withOffset1;
    797  * out ivec4 withOffset2;
    798  * out ivec4 withOffset3;
    799  *
    800  * Bind samplerWithoutOffset to texture unit 0.
    801  * Bind samplerWithOffset to texture unit 1.
    802  *
    803  * Initialize a buffer object to be assigned as input attribute tgoOffset
    804  * data source. The buffer object should hold 128 integer tuples. Fill it
    805  * with some random integer values but falling into a range of
    806  * (MIN_PROGRAM_TEXTURE_GATHER_OFFSET,
    807  *  MAX_PROGRAM_TEXTURE_GATHER_OFFSET).
    808  *
    809  * Initialize a buffer object to be assigned as input attribute texCoords
    810  * data source. The buffer object should hold 128 elements. Fill the first
    811  * 4 tuples with (0.0, 0.0) , (0.0, 1.0), (1.0, 0.0), (1.0, 1.0) and the
    812  * rest with some random float values in the range [-8.0..8.0].
    813  *
    814  * In the vertex shader perform the following operation:
    815  *
    816  * vec2 floorTexCoords = floor(texCoords);
    817  * vec2 fractTexCoords = texCoords - floorTexCoords;
    818  *
    819  * withoutOffset0 = textureGather(samplerWithoutOffset,fractTexCoords, 0);
    820  * withoutOffset1 = textureGather(samplerWithoutOffset,fractTexCoords, 1);
    821  * intFloorTexCoords  = ivec2(int(floorTexCoords.x),int(floorTexCoords.y));
    822  *
    823  * withOffset0 = textureGatherOffset(samplerWithOffset,
    824  *                 texCoords, tgoOffset, 0);
    825  * withOffset1 = textureGatherOffset(samplerWithOffset,
    826  *                 texCoords, tgoOffset, 1);
    827  * withOffset2 = textureGatherOffset(samplerWithOffset,
    828  *                 texCoords, tgoOffset, 2);
    829  * withOffset3 = textureGatherOffset(samplerWithOffset,
    830  *                 texCoords, tgoOffset, 3);
    831  *
    832  * Configure transform feedback to capture the values of withoutOffset*,
    833  * withOffset* and intFloorTexCoords.
    834  *
    835  * Write a boilerplate fragment shader.
    836  *
    837  * Create a program from the above vertex shader and fragment shader
    838  * and use it.
    839  *
    840  * Execute a draw call glDrawArrays(GL_POINTS, 0, 128).
    841  *
    842  * Copy the captured results from the buffer objects bound to transform
    843  * feedback binding points.
    844  *
    845  * Using the captured values for each of the 128 results perform
    846  * the following algorithm:
    847  *
    848  * From the captured withoutOffset0 and withoutOffset1 variables extract
    849  * 4 texelPos values
    850  *
    851  * (Pseudocode)
    852  *
    853  * texelPos[i] = ivec2( withoutOffset0[i] , withoutOffset1[i] );
    854  *
    855  * Find a texel that has not been clamped. It's value should be
    856  * different than (texWidth, texHeight). Let's asume that the found
    857  * texel has index 'foundIndex'.
    858  *
    859  * If we can't find such texel we must throw an exception, because it means
    860  * that the sampling algorithm has failed.
    861  *
    862  * Extract the offset that has to be applied to the chosen texel to get it's
    863  * absolute position (the one we would get if we haven't clamped the texture
    864  * coordinates for textureGather to the range [0,1])
    865  *
    866  * (Pseudocode)
    867  *
    868  * ivec2 absoluteOffset = ivec2( intFloorTexCoords.x * texWidth ,
    869  *                               intFloorTexCoords.y * texHeight );
    870  *
    871  * Next apply the offset to the texel position
    872  *
    873  * (Pseudocode)
    874  *
    875  * texelAbsolutePos[foundIndex] = texelPos[foundIndex] + absoluteOffset;
    876  *
    877  * Now we have to set the absolute positions of the remaining 3 texels.
    878  * We can do this because the foundIndex gives us information which
    879  * texel we are dealing with in a 2x2 texel matrix returned by
    880  * textureGather. The remaining texels will have their absolute positions
    881  * computed by adding or substacting 1 to their x and y components
    882  * depending on their position in the matrix relative to foundIndex.
    883  *
    884  * In the next step we have to apply the offset used in
    885  * textureGatherOffset function to each of the absolute positions.
    886  *
    887  * (Pseudocode)
    888  *
    889  * texelAbsolutePos[i] += tgoOffset;
    890  *
    891  * We have to examine each absolute position in order to know if it should
    892  * been clamped or not.
    893  *
    894  * In case of CLAMP_TO_BORDER_EXT if the absolute position goes beyond the
    895  * texture bounds set it to value of GL_TEXTURE_BORDER_COLOR_EXT -> (-1,-1)
    896  *
    897  * In case of CLAMP_TO_EDGE if the absolute position goes beyond the
    898  * texture bounds we have to clamp the value of absolute position
    899  * to the edge that has been crossed.
    900  *
    901  * The test passes for each of the 4 absolute positions we have
    902  *
    903  * (Pseudocode)
    904  *
    905  * texelAbsolutePos[i] == ivec2( withOffset0[i], withOffset1[i] ) and
    906  * texelAbsolutePos[i] == ivec2( withOffset2[i], withOffset3[i] ).
    907  **/
    908 
    909 /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2D, function textureGatherOffset
    910  */
    911 class GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest
    912 	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
    913 {
    914 public:
    915 	/* Public methods */
    916 	GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
    917 															  const char* name, const char* description);
    918 
    919 	virtual ~GPUShader5TextureGatherOffsetColor2DClampToBorderCaseTest(void)
    920 	{
    921 	}
    922 
    923 protected:
    924 	/* Protected methods */
    925 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    926 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
    927 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    928 
    929 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
    930 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    931 
    932 	virtual void initTest(void);
    933 
    934 private:
    935 	/* Private fields */
    936 	/* Vertex shader code */
    937 	static const glw::GLchar* const m_vertex_shader_code;
    938 };
    939 
    940 /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2D, function textureGatherOffset
    941  */
    942 class GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest
    943 	: public GPUShader5TextureGatherOffsetColor2DRepeatCaseTest
    944 {
    945 public:
    946 	/* Public methods */
    947 	GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
    948 															const char* name, const char* description);
    949 
    950 	virtual ~GPUShader5TextureGatherOffsetColor2DClampToEdgeCaseTest(void)
    951 	{
    952 	}
    953 
    954 protected:
    955 	/* Protected methods */
    956 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    957 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
    958 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    959 
    960 	/* Virtual methods from GPUShader5TextureGatherOffsetColorTestBase */
    961 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    962 	virtual void initTest(void);
    963 
    964 private:
    965 	/* Private fields */
    966 	/* Vertex shader code */
    967 	static const glw::GLchar* const m_vertex_shader_code;
    968 };
    969 
    970 /** Test configuration: wrap mode GL_CLAMP_TO_BORDER_EXT, sampler isampler2DShadow, function textureGatherOffset, axis X
    971  */
    972 class GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest
    973 	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
    974 {
    975 public:
    976 	/* Public methods */
    977 	GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(Context& context, const ExtParameters& extParams,
    978 															  const char* name, const char* description);
    979 
    980 	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToBorderCaseTest(void)
    981 	{
    982 	}
    983 
    984 protected:
    985 	/* Protected methods */
    986 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
    987 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
    988 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
    989 	virtual void prepareVertexBuffersData(std::vector<VertexBufferInfo>& vertex_buffer_infos);
    990 
    991 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
    992 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
    993 
    994 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
    995 	virtual void initTest(void);
    996 
    997 private:
    998 	/* Private fields */
    999 	/* Vertex shader code */
   1000 	static const glw::GLchar* const m_vertex_shader_code;
   1001 };
   1002 
   1003 /** Test configuration: wrap mode GL_CLAMP_TO_EDGE, sampler isampler2DShadow, function textureGatherOffset, axis X
   1004  */
   1005 class GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest
   1006 	: public GPUShader5TextureGatherOffsetDepth2DRepeatCaseTest
   1007 {
   1008 public:
   1009 	/* Public methods */
   1010 	GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(Context& context, const ExtParameters& extParams,
   1011 															const char* name, const char* description);
   1012 
   1013 	virtual ~GPUShader5TextureGatherOffsetDepth2DClampToEdgeCaseTest(void)
   1014 	{
   1015 	}
   1016 
   1017 protected:
   1018 	/* Protected methods */
   1019 	/* Virtual methods from GPUShader5TextureGatherOffsetTestBase */
   1020 	virtual void getTextureWrapMode(glw::GLenum& out_wrap_mode);
   1021 	virtual void getShaderParts(std::vector<const glw::GLchar*>& out_vertex_shader_parts);
   1022 
   1023 	/* Virtual methods from GPUShader5TextureGatherOffsetDepthTestBase */
   1024 	virtual bool checkResult(const CapturedVaryings& captured_data, unsigned int index, unsigned int texture_size);
   1025 
   1026 	virtual void getVaryings(std::vector<const glw::GLchar*>& out_captured_varyings);
   1027 	virtual void initTest(void);
   1028 
   1029 private:
   1030 	/* Private fields */
   1031 	/* Vertex shader code */
   1032 	static const glw::GLchar* const m_vertex_shader_code;
   1033 };
   1034 
   1035 } /* glcts */
   1036 
   1037 #endif // _ESEXTCGPUSHADER5TEXTUREGATHEROFFSET_HPP
   1038